From ab8c4420a90ccb492b1ec41690f23528cc6646f7 Mon Sep 17 00:00:00 2001
From: Ismail Alidzhikov <9372594+ialidzhikov@users.noreply.github.com>
Date: Thu, 30 Oct 2025 19:53:43 +0200
Subject: [PATCH 001/176] Move defaulting of the Shoot networks from the
`ShootValidator` to the `ShootMutator` admission plugin (part 3) (#13207)
* Fetch the Seed resource in the `ShootMutator` admission plugin
* Fix integration tests
* Duplicate defaulting of Shoot networks in the `ShootMutator` admission plugin
* Clean up defaulting of Shoot networks from the `ShootValidator` admission plugin
* Update `ShootMutator` docs
* Wait until the caches have been synced
* Add nil check for Seed `.spec.networks.shootDefaults.{pods,services}`
* Address PR review feedback from acumino
---
docs/concepts/apiserver-admission-plugins.md | 1 +
plugin/pkg/shoot/mutator/admission.go | 91 ++++++++++++
plugin/pkg/shoot/mutator/admission_test.go | 133 +++++++++++++++++-
plugin/pkg/shoot/validator/admission.go | 28 +---
plugin/pkg/shoot/validator/admission_test.go | 22 ---
.../shootvalidator_suite_test.go | 4 -
.../shootvalidator/shootvalidator_test.go | 6 +-
.../bastion/bastion_suite_test.go | 2 +-
.../shoot/migration/migration_suite_test.go | 2 +-
.../shootstate/shootstate_suite_test.go | 2 +-
.../gardenlet/shoot/state/state_suite_test.go | 2 +-
.../shoot/status/status_suite_test.go | 2 +-
12 files changed, 240 insertions(+), 55 deletions(-)
diff --git a/docs/concepts/apiserver-admission-plugins.md b/docs/concepts/apiserver-admission-plugins.md
index 2c45f1718c2..a181bdd197f 100644
--- a/docs/concepts/apiserver-admission-plugins.md
+++ b/docs/concepts/apiserver-admission-plugins.md
@@ -235,6 +235,7 @@ This admission controller reacts on `CREATE` and `UPDATE` operations for `Shoot`
It mutates the `Shoot` in the following way:
- It sets the `gardener.cloud/created-by=` annotation for newly created `Shoot` resources.
- It maintains annotations used for Shoot lifecycle operations such as `shoot.gardener.cloud/tasks` and `maintenance.shoot.gardener.cloud/needs-retry-operation`.
+- It defaults Shoot `.spec.networking.pods` and `.spec.networking.services` fields in case they are not provided and the Seed specifies the `.spec.networks.shootDefaults` field.
Over time, the `ShootMutator` admission plugin will take over all the mutations that are performed by `ShootValidator`.
For more details, see https://github.com/gardener/gardener/issues/2158.
diff --git a/plugin/pkg/shoot/mutator/admission.go b/plugin/pkg/shoot/mutator/admission.go
index ac8ee164eec..db3e660ebe7 100644
--- a/plugin/pkg/shoot/mutator/admission.go
+++ b/plugin/pkg/shoot/mutator/admission.go
@@ -6,8 +6,12 @@ package mutator
import (
"context"
+ "errors"
+ "fmt"
"io"
+ "net"
"reflect"
+ "slices"
apiequality "k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -17,7 +21,12 @@ import (
"k8s.io/utils/ptr"
"github.com/gardener/gardener/pkg/apis/core"
+ "github.com/gardener/gardener/pkg/apis/core/helper"
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ admissioninitializer "github.com/gardener/gardener/pkg/apiserver/admission/initializer"
+ gardencoreinformers "github.com/gardener/gardener/pkg/client/core/informers/externalversions"
+ gardencorev1beta1listers "github.com/gardener/gardener/pkg/client/core/listers/core/v1beta1"
"github.com/gardener/gardener/pkg/controllerutils"
plugin "github.com/gardener/gardener/plugin/pkg"
)
@@ -32,8 +41,17 @@ func Register(plugins *admission.Plugins) {
// MutateShoot is an implementation of admission.Interface.
type MutateShoot struct {
*admission.Handler
+
+ seedLister gardencorev1beta1listers.SeedLister
+ readyFunc admission.ReadyFunc
}
+var (
+ _ = admissioninitializer.WantsCoreInformerFactory(&MutateShoot{})
+
+ readyFuncs []admission.ReadyFunc
+)
+
// New creates a new MutateShoot admission plugin.
func New() (*MutateShoot, error) {
return &MutateShoot{
@@ -41,10 +59,50 @@ func New() (*MutateShoot, error) {
}, nil
}
+// AssignReadyFunc assigns the ready function to the admission handler.
+func (m *MutateShoot) AssignReadyFunc(f admission.ReadyFunc) {
+ m.readyFunc = f
+ m.SetReadyFunc(f)
+}
+
+// SetCoreInformerFactory gets Lister from SharedInformerFactory.
+func (m *MutateShoot) SetCoreInformerFactory(f gardencoreinformers.SharedInformerFactory) {
+ seedInformer := f.Core().V1beta1().Seeds()
+ m.seedLister = seedInformer.Lister()
+
+ readyFuncs = append(
+ readyFuncs,
+ seedInformer.Informer().HasSynced,
+ )
+}
+
+// ValidateInitialization checks whether the plugin was correctly initialized.
+func (m *MutateShoot) ValidateInitialization() error {
+ if m.seedLister == nil {
+ return errors.New("missing seed lister")
+ }
+ return nil
+}
+
var _ admission.MutationInterface = (*MutateShoot)(nil)
// Admit mutates the Shoot.
func (m *MutateShoot) Admit(_ context.Context, a admission.Attributes, _ admission.ObjectInterfaces) error {
+ // Wait until the caches have been synced
+ if m.readyFunc == nil {
+ m.AssignReadyFunc(func() bool {
+ for _, readyFunc := range readyFuncs {
+ if !readyFunc() {
+ return false
+ }
+ }
+ return true
+ })
+ }
+ if !m.WaitForReady() {
+ return admission.NewForbidden(a, errors.New("not yet ready to handle request"))
+ }
+
// Ignore all kinds other than Shoot
if a.GetKind().GroupKind() != core.Kind("Shoot") {
return nil
@@ -67,7 +125,17 @@ func (m *MutateShoot) Admit(_ context.Context, a admission.Attributes, _ admissi
}
}
+ var seed *gardencorev1beta1.Seed
+ if shoot.Spec.SeedName != nil {
+ var err error
+ seed, err = m.seedLister.Get(*shoot.Spec.SeedName)
+ if err != nil {
+ return apierrors.NewInternalError(fmt.Errorf("could not find referenced seed %q: %w", *shoot.Spec.SeedName, err))
+ }
+ }
+
mutationContext := &mutationContext{
+ seed: seed,
shoot: shoot,
oldShoot: oldShoot,
}
@@ -77,11 +145,13 @@ func (m *MutateShoot) Admit(_ context.Context, a admission.Attributes, _ admissi
}
mutationContext.addMetadataAnnotations(a)
+ mutationContext.defaultShootNetworks(helper.IsWorkerless(shoot))
return nil
}
type mutationContext struct {
+ seed *gardencorev1beta1.Seed
shoot *core.Shoot
oldShoot *core.Shoot
}
@@ -157,3 +227,24 @@ func addDeploymentTasks(shoot *core.Shoot, tasks ...string) {
}
controllerutils.AddTasks(shoot.Annotations, tasks...)
}
+
+func (c *mutationContext) defaultShootNetworks(workerless bool) {
+ if c.seed != nil {
+ if c.shoot.Spec.Networking.Pods == nil && !workerless &&
+ c.seed.Spec.Networks.ShootDefaults != nil && c.seed.Spec.Networks.ShootDefaults.Pods != nil &&
+ cidrMatchesIPFamily(*c.seed.Spec.Networks.ShootDefaults.Pods, c.shoot.Spec.Networking.IPFamilies) {
+ c.shoot.Spec.Networking.Pods = c.seed.Spec.Networks.ShootDefaults.Pods
+ }
+
+ if c.shoot.Spec.Networking.Services == nil &&
+ c.seed.Spec.Networks.ShootDefaults != nil && c.seed.Spec.Networks.ShootDefaults.Services != nil &&
+ cidrMatchesIPFamily(*c.seed.Spec.Networks.ShootDefaults.Services, c.shoot.Spec.Networking.IPFamilies) {
+ c.shoot.Spec.Networking.Services = c.seed.Spec.Networks.ShootDefaults.Services
+ }
+ }
+}
+
+func cidrMatchesIPFamily(cidr string, ipfamilies []core.IPFamily) bool {
+ ip, _, _ := net.ParseCIDR(cidr)
+ return ip != nil && (ip.To4() != nil && slices.Contains(ipfamilies, core.IPFamilyIPv4) || ip.To4() == nil && slices.Contains(ipfamilies, core.IPFamilyIPv6))
+}
diff --git a/plugin/pkg/shoot/mutator/admission_test.go b/plugin/pkg/shoot/mutator/admission_test.go
index 4c7fb303844..d99d88e1513 100644
--- a/plugin/pkg/shoot/mutator/admission_test.go
+++ b/plugin/pkg/shoot/mutator/admission_test.go
@@ -18,7 +18,9 @@ import (
"k8s.io/utils/ptr"
"github.com/gardener/gardener/pkg/apis/core"
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ gardencoreinformers "github.com/gardener/gardener/pkg/client/core/informers/externalversions"
"github.com/gardener/gardener/pkg/controllerutils"
. "github.com/gardener/gardener/pkg/utils/test/matchers"
. "github.com/gardener/gardener/plugin/pkg/shoot/mutator"
@@ -47,13 +49,34 @@ var _ = Describe("mutator", func() {
})
})
+ Describe("#ValidateInitialization", func() {
+ It("should return error if no SeedLister is set", func() {
+ admissionHandler, err := New()
+ Expect(err).NotTo(HaveOccurred())
+
+ err = admissionHandler.ValidateInitialization()
+ Expect(err).To(MatchError("missing seed lister"))
+ })
+
+ It("should not return error if all listers are set", func() {
+ admissionHandler, err := New()
+ Expect(err).NotTo(HaveOccurred())
+ coreInformerFactory := gardencoreinformers.NewSharedInformerFactory(nil, 0)
+ admissionHandler.SetCoreInformerFactory(coreInformerFactory)
+
+ Expect(admissionHandler.ValidateInitialization()).To(Succeed())
+ })
+ })
+
Describe("#Admit", func() {
var (
ctx context.Context
userInfo = &user.DefaultInfo{Name: "foo"}
+ seed gardencorev1beta1.Seed
+ shoot core.Shoot
- shoot core.Shoot
+ coreInformerFactory gardencoreinformers.SharedInformerFactory
admissionHandler *MutateShoot
)
@@ -61,16 +84,33 @@ var _ = Describe("mutator", func() {
BeforeEach(func() {
ctx = context.Background()
+ seed = gardencorev1beta1.Seed{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "seed",
+ },
+ }
shoot = core.Shoot{
ObjectMeta: metav1.ObjectMeta{
Name: "shoot",
Namespace: "garden-my-project",
},
+ Spec: core.ShootSpec{
+ Provider: core.Provider{
+ Workers: []core.Worker{
+ {
+ Name: "worker-name",
+ },
+ },
+ },
+ },
}
var err error
admissionHandler, err = New()
Expect(err).NotTo(HaveOccurred())
+ admissionHandler.AssignReadyFunc(func() bool { return true })
+ coreInformerFactory = gardencoreinformers.NewSharedInformerFactory(nil, 0)
+ admissionHandler.SetCoreInformerFactory(coreInformerFactory)
})
It("should ignore a kind other than shoot", func() {
@@ -110,6 +150,16 @@ var _ = Describe("mutator", func() {
Expect(err).To(MatchError("could not convert old object to Shoot"))
})
+ Context("reference checks", func() {
+ It("should reject because the referenced seed was not found", func() {
+ shoot.Spec.SeedName = ptr.To("seed")
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+
+ err := admissionHandler.Admit(ctx, attrs, nil)
+ Expect(err).To(BeInternalServerError())
+ })
+ })
+
Context("created-by annotation", func() {
It("should add the created-by annotation on shoot creation", func() {
Expect(shoot.Annotations).NotTo(HaveKeyWithValue(v1beta1constants.GardenCreatedBy, userInfo.Name))
@@ -328,5 +378,86 @@ var _ = Describe("mutator", func() {
),
)
})
+
+ Context("networking settings", func() {
+ var (
+ podsCIDR = "100.96.0.0/11"
+ servicesCIDR = "100.64.0.0/13"
+ )
+
+ BeforeEach(func() {
+ seed.Spec.Networks.ShootDefaults = &gardencorev1beta1.ShootNetworks{
+ Pods: &podsCIDR,
+ Services: &servicesCIDR,
+ }
+ shoot.Spec.SeedName = ptr.To(seed.Name)
+ shoot.Spec.Networking = &core.Networking{
+ Pods: nil,
+ Services: nil,
+ IPFamilies: []core.IPFamily{core.IPFamilyIPv4},
+ }
+ })
+
+ It("should not default shoot networks if shoot .spec.seedName is nil", func() {
+ shoot.Spec.SeedName = nil
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).NotTo(HaveOccurred())
+ Expect(shoot.Spec.Networking.Pods).To(BeNil())
+ Expect(shoot.Spec.Networking.Services).To(BeNil())
+ })
+
+ It("should not default shoot networks if seed .spec.networks.shootDefaults is empty", func() {
+ seed.Spec.Networks.ShootDefaults = &gardencorev1beta1.ShootNetworks{}
+
+ Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).NotTo(HaveOccurred())
+ Expect(shoot.Spec.Networking.Pods).To(BeNil())
+ Expect(shoot.Spec.Networking.Services).To(BeNil())
+ })
+
+ It("should not default shoot pod network if shoot is workerless", func() {
+ shoot.Spec.Provider.Workers = nil
+
+ Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).NotTo(HaveOccurred())
+ Expect(shoot.Spec.Networking.Pods).To(BeNil())
+ Expect(shoot.Spec.Networking.Services).To(Equal(&servicesCIDR))
+ })
+
+ It("should not default shoot networks if shoot IP family does not match seed .spec.networks.shootDefaults", func() {
+ shoot.Spec.Networking.IPFamilies = []core.IPFamily{core.IPFamilyIPv6}
+
+ Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).NotTo(HaveOccurred())
+ Expect(shoot.Spec.Networking.Pods).To(BeNil())
+ Expect(shoot.Spec.Networking.Services).To(BeNil())
+ })
+
+ It("should default shoot networks if all conditions are met", func() {
+ Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).NotTo(HaveOccurred())
+ Expect(shoot.Spec.Networking.Pods).To(Equal(&podsCIDR))
+ Expect(shoot.Spec.Networking.Services).To(Equal(&servicesCIDR))
+ })
+ })
})
})
diff --git a/plugin/pkg/shoot/validator/admission.go b/plugin/pkg/shoot/validator/admission.go
index d2dcdaf75ac..a1d2c3a71fe 100644
--- a/plugin/pkg/shoot/validator/admission.go
+++ b/plugin/pkg/shoot/validator/admission.go
@@ -9,7 +9,6 @@ import (
"errors"
"fmt"
"io"
- "net"
"reflect"
"slices"
"strconv"
@@ -859,11 +858,6 @@ func (c *validationContext) validateReferencedSecret(secretLister kubecorev1list
return nil
}
-func cidrMatchesIPFamily(cidr string, ipfamilies []core.IPFamily) bool {
- ip, _, _ := net.ParseCIDR(cidr)
- return ip != nil && (ip.To4() != nil && slices.Contains(ipfamilies, core.IPFamilyIPv4) || ip.To4() == nil && slices.Contains(ipfamilies, core.IPFamilyIPv6))
-}
-
func (c *validationContext) validateShootNetworks(a admission.Attributes, workerless bool) field.ErrorList {
var (
allErrs field.ErrorList
@@ -875,24 +869,14 @@ func (c *validationContext) validateShootNetworks(a admission.Attributes, worker
}
if c.seed != nil {
- if c.shoot.Spec.Networking.Pods == nil && !workerless {
- if c.seed.Spec.Networks.ShootDefaults != nil {
- if cidrMatchesIPFamily(*c.seed.Spec.Networks.ShootDefaults.Pods, c.shoot.Spec.Networking.IPFamilies) {
- c.shoot.Spec.Networking.Pods = c.seed.Spec.Networks.ShootDefaults.Pods
- }
- } else if slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv4) {
- allErrs = append(allErrs, field.Required(path.Child("pods"), "pods is required"))
- }
+ if c.shoot.Spec.Networking.Pods == nil && !workerless &&
+ slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv4) {
+ allErrs = append(allErrs, field.Required(path.Child("pods"), "pods is required"))
}
- if c.shoot.Spec.Networking.Services == nil {
- if c.seed.Spec.Networks.ShootDefaults != nil {
- if cidrMatchesIPFamily(*c.seed.Spec.Networks.ShootDefaults.Services, c.shoot.Spec.Networking.IPFamilies) {
- c.shoot.Spec.Networking.Services = c.seed.Spec.Networks.ShootDefaults.Services
- }
- } else if slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv4) {
- allErrs = append(allErrs, field.Required(path.Child("services"), "services is required"))
- }
+ if c.shoot.Spec.Networking.Services == nil &&
+ slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv4) {
+ allErrs = append(allErrs, field.Required(path.Child("services"), "services is required"))
}
if slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv4) {
diff --git a/plugin/pkg/shoot/validator/admission_test.go b/plugin/pkg/shoot/validator/admission_test.go
index eeb60556c73..42c64e7c8b3 100644
--- a/plugin/pkg/shoot/validator/admission_test.go
+++ b/plugin/pkg/shoot/validator/admission_test.go
@@ -2322,28 +2322,6 @@ var _ = Describe("validator", func() {
})
- It("should default shoot networks if seed provides ShootDefaults", func() {
- seed.Spec.Networks.ShootDefaults = &gardencorev1beta1.ShootNetworks{
- Pods: &podsCIDR,
- Services: &servicesCIDR,
- }
- shoot.Spec.Networking.Pods = nil
- shoot.Spec.Networking.Services = nil
-
- Expect(coreInformerFactory.Core().V1beta1().Projects().Informer().GetStore().Add(&project)).To(Succeed())
- Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(&cloudProfile)).To(Succeed())
- Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
- Expect(coreInformerFactory.Core().V1beta1().SecretBindings().Informer().GetStore().Add(&secretBinding)).To(Succeed())
- Expect(securityInformerFactory.Security().V1alpha1().CredentialsBindings().Informer().GetStore().Add(&credentialsBinding)).To(Succeed())
-
- attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
- err := admissionHandler.Admit(ctx, attrs, nil)
-
- Expect(err).NotTo(HaveOccurred())
- Expect(shoot.Spec.Networking.Pods).To(Equal(&podsCIDR))
- Expect(shoot.Spec.Networking.Services).To(Equal(&servicesCIDR))
- })
-
It("should reject because the shoot node and the seed node networks intersect (HA control plane)", func() {
shoot.Spec.Networking.Nodes = &seedNodesCIDR
shoot.Spec.ControlPlane = &core.ControlPlane{HighAvailability: &core.HighAvailability{FailureTolerance: core.FailureTolerance{Type: core.FailureToleranceTypeZone}}}
diff --git a/test/integration/apiserver/admissionplugins/shootvalidator/shootvalidator_suite_test.go b/test/integration/apiserver/admissionplugins/shootvalidator/shootvalidator_suite_test.go
index c4487b374f9..eb582ec7fd8 100644
--- a/test/integration/apiserver/admissionplugins/shootvalidator/shootvalidator_suite_test.go
+++ b/test/integration/apiserver/admissionplugins/shootvalidator/shootvalidator_suite_test.go
@@ -322,10 +322,6 @@ var _ = BeforeSuite(func() {
Pods: "10.0.0.0/16",
Services: "10.1.0.0/16",
Nodes: ptr.To("10.2.0.0/16"),
- ShootDefaults: &gardencorev1beta1.ShootNetworks{
- Pods: ptr.To("100.128.0.0/11"),
- Services: ptr.To("100.72.0.0/13"),
- },
},
},
}
diff --git a/test/integration/apiserver/admissionplugins/shootvalidator/shootvalidator_test.go b/test/integration/apiserver/admissionplugins/shootvalidator/shootvalidator_test.go
index 9617c45746d..3c05f9e8b7a 100644
--- a/test/integration/apiserver/admissionplugins/shootvalidator/shootvalidator_test.go
+++ b/test/integration/apiserver/admissionplugins/shootvalidator/shootvalidator_test.go
@@ -49,7 +49,11 @@ var _ = Describe("ShootValidator tests", func() {
},
},
Kubernetes: gardencorev1beta1.Kubernetes{Version: "1.31.1"},
- Networking: &gardencorev1beta1.Networking{Type: ptr.To("foo-networking")},
+ Networking: &gardencorev1beta1.Networking{
+ Type: ptr.To("foo-networking"),
+ Pods: ptr.To("100.128.0.0/11"),
+ Services: ptr.To("100.72.0.0/13"),
+ },
},
}
})
diff --git a/test/integration/controllermanager/bastion/bastion_suite_test.go b/test/integration/controllermanager/bastion/bastion_suite_test.go
index 9d38837a036..24faf9f0a5b 100644
--- a/test/integration/controllermanager/bastion/bastion_suite_test.go
+++ b/test/integration/controllermanager/bastion/bastion_suite_test.go
@@ -69,7 +69,7 @@ var _ = BeforeSuite(func() {
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
Args: []string{
- "--disable-admission-plugins=Bastion,DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator",
+ "--disable-admission-plugins=Bastion,DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ShootMutator",
},
},
}
diff --git a/test/integration/controllermanager/shoot/migration/migration_suite_test.go b/test/integration/controllermanager/shoot/migration/migration_suite_test.go
index f049c4817fa..88435c39f7d 100644
--- a/test/integration/controllermanager/shoot/migration/migration_suite_test.go
+++ b/test/integration/controllermanager/shoot/migration/migration_suite_test.go
@@ -56,7 +56,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/shootstate/shootstate_suite_test.go b/test/integration/controllermanager/shootstate/shootstate_suite_test.go
index 3d386b5a2e7..ae6ce7f3154 100644
--- a/test/integration/controllermanager/shootstate/shootstate_suite_test.go
+++ b/test/integration/controllermanager/shootstate/shootstate_suite_test.go
@@ -63,7 +63,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/gardenlet/shoot/state/state_suite_test.go b/test/integration/gardenlet/shoot/state/state_suite_test.go
index 943ba851706..403528d2964 100644
--- a/test/integration/gardenlet/shoot/state/state_suite_test.go
+++ b/test/integration/gardenlet/shoot/state/state_suite_test.go
@@ -91,7 +91,7 @@ var _ = BeforeSuite(func() {
},
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
Args: []string{
- "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator",
+ "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ShootMutator",
},
},
}
diff --git a/test/integration/gardenlet/shoot/status/status_suite_test.go b/test/integration/gardenlet/shoot/status/status_suite_test.go
index bfe17b5de49..f6ecfc54a43 100644
--- a/test/integration/gardenlet/shoot/status/status_suite_test.go
+++ b/test/integration/gardenlet/shoot/status/status_suite_test.go
@@ -77,7 +77,7 @@ var _ = BeforeSuite(func() {
},
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
Args: []string{
- "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator",
+ "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ShootMutator",
},
},
}
From c4d228456f95d54608320fd102737fc3fa8e480a Mon Sep 17 00:00:00 2001
From: Johannes Scheerer
Date: Thu, 30 Oct 2025 18:53:50 +0100
Subject: [PATCH 002/176] Upgrade `k8s.io/*` to `v0.34.1`,
`sigs.k8s.io/controller-runtime` to `v0.22.3`, `sigs.k8s.io/controller-tools`
to `v0.19.0` (#13238)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Upgrade k8s.io/* to `v0.34.1`
* Run `make tidy` and `make generate`
* Upgrade controller-runtime to `v0.22.3`
* Upgrade controller-tools to `v0.19.0`
* Run `make generate`
* Use `ReconciliationTimeout` in controller options instead of custom context handling
* Removed seedmanagement/applyconfiguration and
settings/applyconfiguration.
In the past, the corresponding packages were autogenerated, but since
PR#8851 they are no longer updated. It does not look like we actually
need them. Hence, removing them seems like the better option compared to
re-enabling autogeneration.
As a plus, this enables us to get rid of a direct dependency.
* Adapt tests to `controller-runtime` changes.
`.metadata.creationTimestamp` is no longer necessary to be set.
`.preferences` is no longer necessary for kubeconfigs to be set.
* Adapt tests for leader election validation changes (`ErrorTypeInvalid` => `ErrorTypeRequired`)
* Adapt webhook tests to include new caching options
* Adapt test to new validation error messages
* Adapt fake client usage with custom resources including structs as
pointer.
Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
The resulting error looked like the following:
```
[38;5;13m• [PANICKED] [0.025 seconds][0m
[0mController [38;5;13m[1m#MachineConditionChangedPredicate [BeforeEach] [0m#Create [38;5;243mshould return false when object is not machine[0m
[38;5;13m[BeforeEach][0m [38;5;243m/home/prow/go/src/github.com/gardener/gardener/extensions/pkg/controller/worker/controller_test.go:38[0m
[38;5;243m[It] /home/prow/go/src/github.com/gardener/gardener/extensions/pkg/controller/worker/controller_test.go:90[0m
[38;5;13m[PANICKED] Test Panicked[0m
[38;5;13mIn [1m[BeforeEach][0m[38;5;13m at: [1m/usr/local/go/src/reflect/value.go:1261[0m [38;5;243m@ 10/22/25 18:55:14.308[0m
[38;5;13mreflect: call of reflect.Value.Field on ptr Value[0m
```
Changing the inclusion from pointer to non-pointer inclusion solves the
issue, but just using a different object tracker seems less invasive.
* Use utility functions for `TypeMeta` access.
The fake client now clears `TypeMeta`. Hence, we need to use utility
functions if we need to get the actual group/kind of resource objects.
* Adapt tests to fake client clearing `TypeMeta`
* Adapt test to fake client panicing on `Raw` structs being set together with `Object`
---
charts/gardener/gardenlet/test/chart_test.go | 8 +-
charts/gardener/gardenlet/test/test.go | 8 -
.../operator/templates/crd-extensions.yaml | 2 +-
.../operator/templates/crd-gardens.yaml | 2 +-
...rd-operator.gardener.cloud_extensions.yaml | 2 +-
...0-crd-operator.gardener.cloud_gardens.yaml | 2 +-
...urces.gardener.cloud_managedresources.yaml | 2 +-
...s.io_verticalpodautoscalercheckpoints.yaml | 2 +-
...scaling.k8s.io_verticalpodautoscalers.yaml | 2 +-
...tensions.gardener.cloud_backupbuckets.yaml | 2 +-
...tensions.gardener.cloud_backupentries.yaml | 2 +-
...rd-extensions.gardener.cloud_bastions.yaml | 2 +-
...rd-extensions.gardener.cloud_clusters.yaml | 2 +-
...ions.gardener.cloud_containerruntimes.yaml | 2 +-
...tensions.gardener.cloud_controlplanes.yaml | 2 +-
...-extensions.gardener.cloud_dnsrecords.yaml | 2 +-
...-extensions.gardener.cloud_extensions.yaml | 2 +-
...nsions.gardener.cloud_infrastructures.yaml | 2 +-
...rd-extensions.gardener.cloud_networks.yaml | 2 +-
...gardener.cloud_operatingsystemconfigs.yaml | 2 +-
...crd-extensions.gardener.cloud_workers.yaml | 7 +-
...rd-fluentbit.fluent.io_clusterfilters.yaml | 2 +-
...bit.fluent.io_clusterfluentbitconfigs.yaml | 2 +-
...crd-fluentbit.fluent.io_clusterinputs.yaml | 2 +-
...bit.fluent.io_clustermultilineparsers.yaml | 2 +-
...rd-fluentbit.fluent.io_clusteroutputs.yaml | 2 +-
...rd-fluentbit.fluent.io_clusterparsers.yaml | 2 +-
...10-crd-fluentbit.fluent.io_collectors.yaml | 140 ++++-
.../10-crd-fluentbit.fluent.io_filters.yaml | 2 +-
...-fluentbit.fluent.io_fluentbitconfigs.yaml | 2 +-
...10-crd-fluentbit.fluent.io_fluentbits.yaml | 405 +++++++++++++--
...-fluentbit.fluent.io_multilineparsers.yaml | 2 +-
.../10-crd-fluentbit.fluent.io_outputs.yaml | 2 +-
.../10-crd-fluentbit.fluent.io_parsers.yaml | 2 +-
...rd-machine.sapcloud.io_machineclasses.yaml | 2 +-
...achine.sapcloud.io_machinedeployments.yaml | 7 +-
.../10-crd-machine.sapcloud.io_machines.yaml | 7 +-
...0-crd-machine.sapcloud.io_machinesets.yaml | 7 +-
...toring.coreos.com_alertmanagerconfigs.yaml | 2 +-
...d-monitoring.coreos.com_alertmanagers.yaml | 372 +++++++++++--
...crd-monitoring.coreos.com_podmonitors.yaml | 2 +-
.../10-crd-monitoring.coreos.com_probes.yaml | 2 +-
...onitoring.coreos.com_prometheusagents.yaml | 372 +++++++++++--
...rd-monitoring.coreos.com_prometheuses.yaml | 374 +++++++++++--
...monitoring.coreos.com_prometheusrules.yaml | 2 +-
...d-monitoring.coreos.com_scrapeconfigs.yaml | 2 +-
...monitoring.coreos.com_servicemonitors.yaml | 2 +-
...rd-monitoring.coreos.com_thanosrulers.yaml | 372 +++++++++++--
.../seed-crds/10-crd-perses.dev_perses.yaml | 6 +-
.../10-crd-perses.dev_persesdashboards.yaml | 2 +-
.../10-crd-perses.dev_persesdatasources.yaml | 2 +-
...urces.gardener.cloud_managedresources.yaml | 2 +-
.../genericactuator/actuator_test.go | 3 +-
.../pkg/controller/worker/controller_test.go | 7 +-
.../actuator_reconcile_test.go | 8 +
go.mod | 59 +--
go.sum | 148 +++---
pkg/api/extensions/accessor_test.go | 4 +-
.../v1alpha1/zz_generated.defaults.go | 33 ++
pkg/apiserver/openapi/openapi_generated.go | 412 +++++++++++++--
pkg/client/kubernetes/applier_test.go | 2 +
pkg/client/kubernetes/chartapplier_test.go | 7 -
.../applyconfiguration/internal/internal.go | 50 --
.../seedmanagement/v1alpha1/gardenlet.go | 59 ---
.../v1alpha1/gardenletdeployment.go | 137 -----
.../seedmanagement/v1alpha1/image.go | 49 --
.../seedmanagement/v1alpha1/managedseed.go | 206 --------
.../seedmanagement/v1alpha1/managedseedset.go | 205 --------
.../v1alpha1/managedseedsetspec.go | 77 ---
.../v1alpha1/managedseedsetstatus.go | 123 -----
.../v1alpha1/managedseedspec.go | 36 --
.../v1alpha1/managedseedstatus.go | 42 --
.../v1alpha1/managedseedtemplate.go | 174 -------
.../seedmanagement/v1alpha1/pendingreplica.go | 59 ---
.../v1alpha1/rollingupdatestrategy.go | 27 -
.../seedmanagement/v1alpha1/shoot.go | 27 -
.../seedmanagement/v1alpha1/updatestrategy.go | 40 --
.../applyconfiguration/utils.go | 51 --
.../applyconfiguration/internal/internal.go | 50 --
.../v1alpha1/clusteropenidconnectpreset.go | 195 -------
.../clusteropenidconnectpresetspec.go | 64 ---
.../v1alpha1/kubeapiserveropenidconnect.go | 107 ----
.../openidconnectclientauthentication.go | 42 --
.../settings/v1alpha1/openidconnectpreset.go | 196 -------
.../v1alpha1/openidconnectpresetspec.go | 58 ---
.../settings/applyconfiguration/utils.go | 35 --
...s.io_verticalpodautoscalercheckpoints.yaml | 2 +-
...scaling.k8s.io_verticalpodautoscalers.yaml | 2 +-
...tensions.gardener.cloud_backupbuckets.yaml | 2 +-
...tensions.gardener.cloud_backupentries.yaml | 2 +-
...rd-extensions.gardener.cloud_bastions.yaml | 2 +-
...rd-extensions.gardener.cloud_clusters.yaml | 2 +-
...ions.gardener.cloud_containerruntimes.yaml | 2 +-
...tensions.gardener.cloud_controlplanes.yaml | 2 +-
...-extensions.gardener.cloud_dnsrecords.yaml | 2 +-
...-extensions.gardener.cloud_extensions.yaml | 2 +-
...nsions.gardener.cloud_infrastructures.yaml | 2 +-
...rd-extensions.gardener.cloud_networks.yaml | 2 +-
...gardener.cloud_operatingsystemconfigs.yaml | 2 +-
...crd-extensions.gardener.cloud_workers.yaml | 7 +-
.../components/nodeagent/rbac_test.go | 3 -
.../components/nodeagent/secrets_test.go | 5 +-
.../opentelemetrycollector/config_test.go | 1 -
pkg/component/gardener/access/access_test.go | 2 -
.../gardener/apiserver/apiserver_test.go | 9 +-
...rd-dashboard.gardener.cloud_terminals.yaml | 4 +-
...urces.gardener.cloud_managedresources.yaml | 2 +-
.../resourcemanager/resource_manager_test.go | 2 -
.../kubernetes/apiserver/apiserver_test.go | 9 +-
.../networking/coredns/coredns_test.go | 19 +-
.../istio/test_charts/ingress_namespace.yaml | 1 -
.../test_charts/ingress_servicemonitor.yaml | 1 -
.../istio/test_charts/ingress_telemetry.yaml | 1 -
.../test_charts/istiod_servicemonitor.yaml | 1 -
.../nginxingress/nginxingress_test.go | 35 --
.../nodelocaldns/nodelocaldns_test.go | 10 -
.../dependencywatchdog/access_test.go | 13 +-
.../dependencywatchdog/bootstrap_test.go | 10 -
.../machine_controller_manager_test.go | 4 -
...rd-machine.sapcloud.io_machineclasses.yaml | 2 +-
...achine.sapcloud.io_machinedeployments.yaml | 7 +-
.../crd-machine.sapcloud.io_machines.yaml | 7 +-
.../crd-machine.sapcloud.io_machinesets.yaml | 7 +-
.../node_problem_detector_test.go | 7 -
...rd-fluentbit.fluent.io_clusterfilters.yaml | 2 +-
...bit.fluent.io_clusterfluentbitconfigs.yaml | 2 +-
...crd-fluentbit.fluent.io_clusterinputs.yaml | 2 +-
...bit.fluent.io_clustermultilineparsers.yaml | 2 +-
...rd-fluentbit.fluent.io_clusteroutputs.yaml | 2 +-
...rd-fluentbit.fluent.io_clusterparsers.yaml | 2 +-
.../crd-fluentbit.fluent.io_collectors.yaml | 140 ++++-
.../crd-fluentbit.fluent.io_filters.yaml | 2 +-
...-fluentbit.fluent.io_fluentbitconfigs.yaml | 2 +-
.../crd-fluentbit.fluent.io_fluentbits.yaml | 405 +++++++++++++--
...-fluentbit.fluent.io_multilineparsers.yaml | 2 +-
.../crd-fluentbit.fluent.io_outputs.yaml | 2 +-
.../crd-fluentbit.fluent.io_parsers.yaml | 2 +-
.../blackboxexporter/blackboxexporter_test.go | 9 -
.../metricsserver/metricsserver_test.go | 11 -
.../nodeexporter/nodeexporter_test.go | 5 -
.../templates/crd-perses.dev_perses.yaml | 6 +-
.../crd-perses.dev_persesdashboards.yaml | 2 +-
.../crd-perses.dev_persesdatasources.yaml | 2 +-
...toring.coreos.com_alertmanagerconfigs.yaml | 2 +-
...d-monitoring.coreos.com_alertmanagers.yaml | 372 +++++++++++--
...crd-monitoring.coreos.com_podmonitors.yaml | 2 +-
.../crd-monitoring.coreos.com_probes.yaml | 2 +-
...onitoring.coreos.com_prometheusagents.yaml | 372 +++++++++++--
...rd-monitoring.coreos.com_prometheuses.yaml | 374 +++++++++++--
...monitoring.coreos.com_prometheusrules.yaml | 2 +-
...d-monitoring.coreos.com_scrapeconfigs.yaml | 2 +-
...monitoring.coreos.com_servicemonitors.yaml | 2 +-
...rd-monitoring.coreos.com_thanosrulers.yaml | 372 +++++++++++--
...crd-opentelemetry.io_instrumentations.yaml | 491 +++++++++++++++---
.../crd-opentelemetry.io_opampbridges.yaml | 176 ++++++-
...ntelemetry.io_opentelemetrycollectors.yaml | 460 ++++++++++++++--
...crd-opentelemetry.io_targetallocators.yaml | 400 ++++++++++++--
.../observability/plutono/plutono_test.go | 4 -
pkg/component/seed/system/system_test.go | 5 -
pkg/component/shared/kubeapiserver_test.go | 2 +
pkg/controller/networkpolicy/add.go | 2 +
pkg/controller/networkpolicy/reconciler.go | 3 -
pkg/controller/reference/add.go | 2 +
pkg/controller/reference/reconciler.go | 3 -
pkg/controller/tokenrequestor/add.go | 2 +
pkg/controller/tokenrequestor/reconciler.go | 8 +-
.../tokenrequestor/reconciler_test.go | 1 -
pkg/controller/vpaevictionrequirements/add.go | 2 +
.../vpaevictionrequirements/reconciler.go | 3 -
.../v1alpha1/validation/validation_test.go | 2 +-
.../controller/bastion/add.go | 2 +
.../controller/bastion/reconciler.go | 4 -
.../certificatesigningrequest/add.go | 2 +
.../certificatesigningrequest/reconciler.go | 4 -
.../controller/cloudprofile/add.go | 2 +
.../controller/cloudprofile/reconciler.go | 3 -
.../controller/controllerdeployment/add.go | 2 +
.../controllerdeployment/reconciler.go | 3 -
.../controllerregistrationfinalizer/add.go | 2 +
.../reconciler.go | 3 -
.../extensionclusterrole/add.go | 6 +-
.../extensionclusterrole/reconciler.go | 3 -
.../controllerregistration/seed/add.go | 2 +
.../controllerregistration/seed/reconciler.go | 3 -
.../seedfinalizer/add.go | 2 +
.../seedfinalizer/reconciler.go | 3 -
.../controller/credentialsbinding/add.go | 2 +
.../credentialsbinding/reconciler.go | 15 +-
pkg/controllermanager/controller/event/add.go | 2 +
.../controller/event/reconciler.go | 4 -
.../controller/exposureclass/add.go | 2 +
.../controller/exposureclass/reconciler.go | 3 -
.../controller/managedseedset/add.go | 1 +
.../controller/managedseedset/reconciler.go | 3 -
.../controller/namespacedcloudprofile/add.go | 1 +
.../namespacedcloudprofile/reconciler.go | 3 -
.../controller/project/activity/add.go | 2 +
.../controller/project/activity/reconciler.go | 4 -
.../controller/project/project/add.go | 2 +
.../controller/project/project/reconciler.go | 3 -
.../controller/project/stale/add.go | 1 +
.../controller/project/stale/reconciler.go | 4 -
pkg/controllermanager/controller/quota/add.go | 2 +
.../controller/quota/reconciler.go | 3 -
.../controller/secretbinding/add.go | 2 +
.../controller/secretbinding/reconciler.go | 3 -
.../controller/seed/backupbucketscheck/add.go | 1 +
.../seed/backupbucketscheck/reconciler.go | 4 -
.../controller/seed/extensionscheck/add.go | 1 +
.../seed/extensionscheck/reconciler.go | 4 -
.../controller/seed/lifecycle/add.go | 1 +
.../controller/seed/lifecycle/reconciler.go | 4 -
.../controller/seed/secrets/add.go | 2 +
.../controller/seed/secrets/reconciler.go | 3 -
.../controller/shoot/conditions/add.go | 2 +
.../controller/shoot/conditions/reconciler.go | 4 -
.../controller/shoot/hibernation/add.go | 2 +
.../shoot/hibernation/reconciler.go | 4 -
.../controller/shoot/maintenance/add.go | 2 +
.../shoot/maintenance/reconciler.go | 3 -
.../controller/shoot/migration/add.go | 2 +
.../controller/shoot/migration/reconciler.go | 4 -
.../controller/shoot/quota/add.go | 1 +
.../controller/shoot/quota/reconciler.go | 4 -
.../controller/shoot/retry/add.go | 2 +
.../controller/shoot/retry/reconciler.go | 4 -
.../controller/shoot/statuslabel/add.go | 2 +
.../shoot/statuslabel/reconciler.go | 4 -
pkg/controllerutils/miscellaneous.go | 8 -
pkg/extensions/cluster_test.go | 7 +-
pkg/gardenadm/staticpod/translator_test.go | 9 -
.../v1alpha1/validation/validation_test.go | 2 +-
pkg/gardenlet/controller/backupbucket/add.go | 2 +
.../controller/backupbucket/reconciler.go | 17 +-
pkg/gardenlet/controller/backupentry/add.go | 2 +
.../controller/backupentry/reconciler.go | 17 +-
pkg/gardenlet/controller/bastion/add.go | 2 +
.../controller/bastion/reconciler.go | 3 +-
.../controllerinstallation/care/add.go | 3 +-
.../controllerinstallation/care/reconciler.go | 3 +-
.../controllerinstallation/add.go | 2 +
.../controllerinstallation/reconciler.go | 3 +-
.../controllerinstallation/required/add.go | 1 +
.../required/reconciler.go | 4 -
pkg/gardenlet/controller/gardenlet/add.go | 1 +
.../controller/gardenlet/reconciler.go | 4 -
pkg/gardenlet/controller/managedseed/add.go | 1 +
.../controller/managedseed/reconciler.go | 3 -
pkg/gardenlet/controller/seed/care/add.go | 3 +-
.../controller/seed/care/reconciler.go | 5 -
pkg/gardenlet/controller/seed/lease/add.go | 1 +
.../controller/seed/lease/reconciler.go | 3 -
pkg/gardenlet/controller/shoot/care/add.go | 3 +-
.../controller/shoot/care/health_test.go | 7 +-
.../controller/shoot/care/reconciler.go | 5 -
.../controller/shoot/shoot/cleaner_test.go | 7 +-
pkg/gardenlet/controller/shoot/state/add.go | 6 +-
.../controller/shoot/state/reconciler.go | 4 -
pkg/gardenlet/controller/shoot/status/add.go | 6 +-
.../controller/shoot/status/reconciler.go | 4 -
.../tokenrequestor/workloadidentity/add.go | 2 +
.../workloadidentity/reconciler.go | 8 +-
.../operation/botanist/kubeapiserver_test.go | 1 -
.../operation/botanist/kubeproxy_test.go | 1 -
.../botanist/machinecontrollermanager_test.go | 7 +-
.../operation/botanist/migration_test.go | 7 +-
pkg/gardenlet/operation/botanist/secrets.go | 10 +-
.../kubelet_bootstrap_kubeconfig_test.go | 1 -
pkg/nodeagent/controller/node/add.go | 6 +-
pkg/nodeagent/controller/node/reconciler.go | 4 -
.../controller/operatingsystemconfig/add.go | 6 +-
.../operatingsystemconfig/reconciler.go | 11 +-
.../operatingsystemconfig/reconciler_test.go | 2 -
pkg/nodeagent/controller/token/add.go | 7 +-
pkg/nodeagent/controller/token/reconciler.go | 4 -
.../v1alpha1/validation/validation_test.go | 2 +-
pkg/operator/controller/extension/care/add.go | 1 +
.../controller/extension/care/reconciler.go | 5 -
.../controller/extension/extension/add.go | 2 +
.../extension/extension/reconciler_delete.go | 6 +-
.../extension/reconciler_reconcile.go | 7 +-
.../extension/required/runtime/add.go | 1 +
.../extension/required/runtime/reconciler.go | 4 -
.../extension/required/virtual/add.go | 2 +
.../extension/required/virtual/reconciler.go | 4 -
pkg/operator/controller/garden/care/add.go | 1 +
.../controller/garden/care/reconciler.go | 5 -
pkg/operator/controller/gardenlet/add.go | 2 +
.../controller/gardenlet/reconciler.go | 4 -
.../v1alpha1/validation/validation_test.go | 2 +-
.../controller/csrapprover/add.go | 2 +
.../controller/csrapprover/reconciler.go | 4 -
.../controller/garbagecollector/add.go | 1 +
.../controller/garbagecollector/reconciler.go | 8 +-
.../controller/health/health/add.go | 1 +
.../controller/health/health/reconciler.go | 6 -
.../controller/health/progressing/add.go | 1 +
.../health/progressing/reconciler.go | 6 -
.../controller/managedresource/add.go | 1 +
.../controller/managedresource/reconciler.go | 14 +-
.../controller/networkpolicy/add.go | 2 +
.../controller/networkpolicy/reconciler.go | 3 -
.../node/agentreconciliationdelay/add.go | 5 +-
.../agentreconciliationdelay/reconciler.go | 8 +-
.../controller/node/criticalcomponents/add.go | 2 +
.../node/criticalcomponents/reconciler.go | 8 +-
.../nodeagentauthorizer/authorizer_test.go | 7 +-
.../v1alpha1/validation/validation_test.go | 2 +-
pkg/scheduler/controller/shoot/add.go | 2 +
pkg/scheduler/controller/shoot/reconciler.go | 4 -
pkg/utils/gardener/machines_test.go | 7 +-
.../gardener/shootstate/shootstate_test.go | 9 +-
pkg/utils/managedresources/registry_test.go | 2 -
.../validation/componentbaseconfig_test.go | 2 +-
pkg/webhook/authorizer/handler_test.go | 12 +-
.../managedseed/validator/admission_test.go | 4 +-
.../operatingsystemconfig_test.go | 3 +-
...gardener.cloud_certificaterevocations.yaml | 2 +-
...-crd-cert.gardener.cloud_certificates.yaml | 2 +-
.../10-crd-cert.gardener.cloud_issuers.yaml | 2 +-
.../mock/client-go/kubernetes/mocks.go | 72 +--
.../mock/controller-runtime/client/mocks.go | 38 ++
322 files changed, 5932 insertions(+), 3571 deletions(-)
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/internal/internal.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/gardenlet.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/gardenletdeployment.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/image.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseed.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedset.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedsetspec.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedsetstatus.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedspec.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedstatus.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedtemplate.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/pendingreplica.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/rollingupdatestrategy.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/shoot.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/updatestrategy.go
delete mode 100644 pkg/client/seedmanagement/applyconfiguration/utils.go
delete mode 100644 pkg/client/settings/applyconfiguration/internal/internal.go
delete mode 100644 pkg/client/settings/applyconfiguration/settings/v1alpha1/clusteropenidconnectpreset.go
delete mode 100644 pkg/client/settings/applyconfiguration/settings/v1alpha1/clusteropenidconnectpresetspec.go
delete mode 100644 pkg/client/settings/applyconfiguration/settings/v1alpha1/kubeapiserveropenidconnect.go
delete mode 100644 pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectclientauthentication.go
delete mode 100644 pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectpreset.go
delete mode 100644 pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectpresetspec.go
delete mode 100644 pkg/client/settings/applyconfiguration/utils.go
diff --git a/charts/gardener/gardenlet/test/chart_test.go b/charts/gardener/gardenlet/test/chart_test.go
index 9456b59afc6..849c41d3a29 100644
--- a/charts/gardener/gardenlet/test/chart_test.go
+++ b/charts/gardener/gardenlet/test/chart_test.go
@@ -356,7 +356,7 @@ var _ = Describe("#Gardenlet Chart Test", func() {
Provider: gardencorev1beta1.SeedProvider{},
},
},
- }, nil, nil, nil, nil, map[string]string{"gardenlet-configmap": "gardenlet-configmap-babc313f"}),
+ }, nil, nil, nil, nil, map[string]string{"gardenlet-configmap": "gardenlet-configmap-f3c6b5a9"}),
Entry("verify deployment with two replica and three zones", nil, nil, nil, nil, nil,
&gardenletconfigv1alpha1.SeedConfig{
SeedTemplate: gardencorev1beta1.SeedTemplate{
@@ -371,7 +371,7 @@ var _ = Describe("#Gardenlet Chart Test", func() {
},
}, &seedmanagement.GardenletDeployment{
ReplicaCount: ptr.To[int32](2),
- }, nil, nil, nil, map[string]string{"gardenlet-configmap": "gardenlet-configmap-39425435"}),
+ }, nil, nil, nil, map[string]string{"gardenlet-configmap": "gardenlet-configmap-7ce49ea8"}),
Entry("verify deployment with only one replica", nil, nil, nil, nil, nil,
&gardenletconfigv1alpha1.SeedConfig{
SeedTemplate: gardencorev1beta1.SeedTemplate{
@@ -386,7 +386,7 @@ var _ = Describe("#Gardenlet Chart Test", func() {
},
}, &seedmanagement.GardenletDeployment{
ReplicaCount: ptr.To[int32](1),
- }, nil, nil, nil, map[string]string{"gardenlet-configmap": "gardenlet-configmap-39425435"}),
+ }, nil, nil, nil, map[string]string{"gardenlet-configmap": "gardenlet-configmap-7ce49ea8"}),
Entry("verify deployment with only one zone", nil, nil, nil, nil, nil,
&gardenletconfigv1alpha1.SeedConfig{
SeedTemplate: gardencorev1beta1.SeedTemplate{
@@ -399,7 +399,7 @@ var _ = Describe("#Gardenlet Chart Test", func() {
},
},
},
- }, nil, nil, nil, nil, map[string]string{"gardenlet-configmap": "gardenlet-configmap-8e8038ec"}),
+ }, nil, nil, nil, nil, map[string]string{"gardenlet-configmap": "gardenlet-configmap-3a4b364a"}),
Entry("verify deployment with image vector override", nil, nil, nil, nil, nil, nil, nil, ptr.To("dummy-override-content"), nil, nil, map[string]string{
"gardenlet-configmap": "gardenlet-configmap-e03f6438",
"gardenlet-imagevector-overwrite": "gardenlet-imagevector-overwrite-32ecb769",
diff --git a/charts/gardener/gardenlet/test/test.go b/charts/gardener/gardenlet/test/test.go
index 9ea34600356..925bdbad7f8 100644
--- a/charts/gardener/gardenlet/test/test.go
+++ b/charts/gardener/gardenlet/test/test.go
@@ -120,7 +120,6 @@ func ValidateGardenletChartRBAC(ctx context.Context, c client.Client, expectedLa
func getGardenletClusterRole(labels map[string]string) *rbacv1.ClusterRole {
return &rbacv1.ClusterRole{
- TypeMeta: metav1.TypeMeta{Kind: "ClusterRole", APIVersion: rbacv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "gardener.cloud:system:gardenlet",
Labels: labels,
@@ -379,7 +378,6 @@ func getGardenletClusterRole(labels map[string]string) *rbacv1.ClusterRole {
func getAPIServerSNIClusterRole(labels map[string]string) *rbacv1.ClusterRole {
return &rbacv1.ClusterRole{
- TypeMeta: metav1.TypeMeta{Kind: "ClusterRole", APIVersion: rbacv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "gardener.cloud:system:gardenlet:apiserver-sni",
Labels: labels,
@@ -409,7 +407,6 @@ func getAPIServerSNIClusterRole(labels map[string]string) *rbacv1.ClusterRole {
func getManagedIstioClusterRole(labels map[string]string) *rbacv1.ClusterRole {
return &rbacv1.ClusterRole{
- TypeMeta: metav1.TypeMeta{Kind: "ClusterRole", APIVersion: rbacv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "gardener.cloud:system:gardenlet:managed-istio",
Labels: labels,
@@ -444,7 +441,6 @@ func getManagedIstioClusterRole(labels map[string]string) *rbacv1.ClusterRole {
func getGardenletClusterRoleBinding(labels map[string]string, serviceAccountName string) *rbacv1.ClusterRoleBinding {
return &rbacv1.ClusterRoleBinding{
- TypeMeta: metav1.TypeMeta{Kind: "ClusterRoleBinding", APIVersion: rbacv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "gardener.cloud:system:gardenlet",
Labels: labels,
@@ -467,7 +463,6 @@ func getGardenletClusterRoleBinding(labels map[string]string, serviceAccountName
func getAPIServerSNIClusterRoleBinding(labels map[string]string, serviceAccountName string) *rbacv1.ClusterRoleBinding {
return &rbacv1.ClusterRoleBinding{
- TypeMeta: metav1.TypeMeta{Kind: "ClusterRoleBinding", APIVersion: rbacv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "gardener.cloud:system:gardenlet:apiserver-sni",
Labels: labels,
@@ -490,7 +485,6 @@ func getAPIServerSNIClusterRoleBinding(labels map[string]string, serviceAccountN
func getManagedIstioClusterRoleBinding(labels map[string]string, serviceAccountName string) *rbacv1.ClusterRoleBinding {
return &rbacv1.ClusterRoleBinding{
- TypeMeta: metav1.TypeMeta{Kind: "ClusterRoleBinding", APIVersion: rbacv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "gardener.cloud:system:gardenlet:managed-istio",
Labels: labels,
@@ -513,7 +507,6 @@ func getManagedIstioClusterRoleBinding(labels map[string]string, serviceAccountN
func getGardenGardenletRole(labels map[string]string) *rbacv1.Role {
return &rbacv1.Role{
- TypeMeta: metav1.TypeMeta{Kind: "Role", APIVersion: rbacv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "gardener.cloud:system:gardenlet",
Namespace: "garden",
@@ -532,7 +525,6 @@ func getGardenGardenletRole(labels map[string]string) *rbacv1.Role {
func getGardenGardenletRoleBinding(labels map[string]string, serviceAccountName string) *rbacv1.RoleBinding {
return &rbacv1.RoleBinding{
- TypeMeta: metav1.TypeMeta{Kind: "RoleBinding", APIVersion: rbacv1.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "gardener.cloud:system:gardenlet",
Namespace: "garden",
diff --git a/charts/gardener/operator/templates/crd-extensions.yaml b/charts/gardener/operator/templates/crd-extensions.yaml
index a8161032712..02f3f6f9872 100644
--- a/charts/gardener/operator/templates/crd-extensions.yaml
+++ b/charts/gardener/operator/templates/crd-extensions.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: extensions.operator.gardener.cloud
spec:
group: operator.gardener.cloud
diff --git a/charts/gardener/operator/templates/crd-gardens.yaml b/charts/gardener/operator/templates/crd-gardens.yaml
index 927de52082f..1892a6751c3 100644
--- a/charts/gardener/operator/templates/crd-gardens.yaml
+++ b/charts/gardener/operator/templates/crd-gardens.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: gardens.operator.gardener.cloud
spec:
group: operator.gardener.cloud
diff --git a/example/operator/10-crd-operator.gardener.cloud_extensions.yaml b/example/operator/10-crd-operator.gardener.cloud_extensions.yaml
index a8161032712..02f3f6f9872 100644
--- a/example/operator/10-crd-operator.gardener.cloud_extensions.yaml
+++ b/example/operator/10-crd-operator.gardener.cloud_extensions.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: extensions.operator.gardener.cloud
spec:
group: operator.gardener.cloud
diff --git a/example/operator/10-crd-operator.gardener.cloud_gardens.yaml b/example/operator/10-crd-operator.gardener.cloud_gardens.yaml
index 927de52082f..1892a6751c3 100644
--- a/example/operator/10-crd-operator.gardener.cloud_gardens.yaml
+++ b/example/operator/10-crd-operator.gardener.cloud_gardens.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: gardens.operator.gardener.cloud
spec:
group: operator.gardener.cloud
diff --git a/example/resource-manager/10-crd-resources.gardener.cloud_managedresources.yaml b/example/resource-manager/10-crd-resources.gardener.cloud_managedresources.yaml
index e24239b49bd..6ce5eeccc11 100644
--- a/example/resource-manager/10-crd-resources.gardener.cloud_managedresources.yaml
+++ b/example/resource-manager/10-crd-resources.gardener.cloud_managedresources.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: managedresources.resources.gardener.cloud
spec:
group: resources.gardener.cloud
diff --git a/example/seed-crds/10-crd-autoscaling.k8s.io_verticalpodautoscalercheckpoints.yaml b/example/seed-crds/10-crd-autoscaling.k8s.io_verticalpodautoscalercheckpoints.yaml
index 3adc7ba1ec4..cc28dc5ab71 100644
--- a/example/seed-crds/10-crd-autoscaling.k8s.io_verticalpodautoscalercheckpoints.yaml
+++ b/example/seed-crds/10-crd-autoscaling.k8s.io_verticalpodautoscalercheckpoints.yaml
@@ -4,7 +4,7 @@ kind: CustomResourceDefinition
metadata:
annotations:
api-approved.kubernetes.io: https://github.com/kubernetes/kubernetes/pull/63797
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: verticalpodautoscalercheckpoints.autoscaling.k8s.io
spec:
group: autoscaling.k8s.io
diff --git a/example/seed-crds/10-crd-autoscaling.k8s.io_verticalpodautoscalers.yaml b/example/seed-crds/10-crd-autoscaling.k8s.io_verticalpodautoscalers.yaml
index 6d1aad35d39..ee3a12bbe6a 100644
--- a/example/seed-crds/10-crd-autoscaling.k8s.io_verticalpodautoscalers.yaml
+++ b/example/seed-crds/10-crd-autoscaling.k8s.io_verticalpodautoscalers.yaml
@@ -4,7 +4,7 @@ kind: CustomResourceDefinition
metadata:
annotations:
api-approved.kubernetes.io: https://github.com/kubernetes/kubernetes/pull/63797
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: verticalpodautoscalers.autoscaling.k8s.io
spec:
group: autoscaling.k8s.io
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_backupbuckets.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_backupbuckets.yaml
index 708d9153fe6..1a8fa9ec50c 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_backupbuckets.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_backupbuckets.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: backupbuckets.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_backupentries.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_backupentries.yaml
index 4302eaf29e8..1a0ce89ac74 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_backupentries.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_backupentries.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: backupentries.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_bastions.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_bastions.yaml
index aa7f591ea91..00138957b66 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_bastions.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_bastions.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: bastions.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_clusters.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_clusters.yaml
index 9b5611899d0..c670d2421b3 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_clusters.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_clusters.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusters.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_containerruntimes.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_containerruntimes.yaml
index 1bad7e86aaf..84e534b215d 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_containerruntimes.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_containerruntimes.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: containerruntimes.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_controlplanes.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_controlplanes.yaml
index 601ef45e4d1..3acaee0b676 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_controlplanes.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_controlplanes.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: controlplanes.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_dnsrecords.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_dnsrecords.yaml
index 85315243dac..3021991231e 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_dnsrecords.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_dnsrecords.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: dnsrecords.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_extensions.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_extensions.yaml
index db5adfb520d..12a7041fc8d 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_extensions.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_extensions.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: extensions.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_infrastructures.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_infrastructures.yaml
index 59f37187695..a829864c14e 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_infrastructures.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_infrastructures.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: infrastructures.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_networks.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_networks.yaml
index 48e36d6074b..062cb41bec7 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_networks.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_networks.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: networks.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_operatingsystemconfigs.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_operatingsystemconfigs.yaml
index fd702609742..d6147b312bf 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_operatingsystemconfigs.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_operatingsystemconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: operatingsystemconfigs.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/example/seed-crds/10-crd-extensions.gardener.cloud_workers.yaml b/example/seed-crds/10-crd-extensions.gardener.cloud_workers.yaml
index 0f06d223d26..b7cf4e013db 100644
--- a/example/seed-crds/10-crd-extensions.gardener.cloud_workers.yaml
+++ b/example/seed-crds/10-crd-extensions.gardener.cloud_workers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: workers.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
@@ -648,9 +648,8 @@ spec:
a node.
type: string
timeAdded:
- description: |-
- TimeAdded represents the time at which the taint was added.
- It is only written for NoExecute taints.
+ description: TimeAdded represents the time at which the
+ taint was added.
format: date-time
type: string
value:
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfilters.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfilters.yaml
index a5789bad004..624039566a0 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfilters.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfilters.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusterfilters.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
index 8506b8bcccc..2aaeb309652 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusterfluentbitconfigs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterinputs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterinputs.yaml
index 7931598ceb0..f3813ba4343 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterinputs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterinputs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusterinputs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clustermultilineparsers.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clustermultilineparsers.yaml
index e6fe12dea7d..e56ff886a2d 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clustermultilineparsers.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clustermultilineparsers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clustermultilineparsers.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusteroutputs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusteroutputs.yaml
index 79e5b28708d..f53fd251fb4 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusteroutputs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusteroutputs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusteroutputs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterparsers.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterparsers.yaml
index e36b427f0b9..0e2983036e5 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterparsers.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterparsers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusterparsers.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_collectors.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_collectors.yaml
index 0f7bc38be2f..c99f8c00ad4 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_collectors.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_collectors.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: collectors.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
@@ -610,8 +610,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -1252,15 +1252,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -1420,13 +1418,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -1514,7 +1510,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2545,15 +2541,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -2735,12 +2729,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -2819,7 +2811,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -3239,6 +3231,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -3373,7 +3470,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_filters.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_filters.yaml
index fcb3d3d56c4..55135835718 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_filters.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_filters.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: filters.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbitconfigs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbitconfigs.yaml
index 55ec28f4b8d..aafe67c640f 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbitconfigs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbitconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: fluentbitconfigs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbits.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbits.yaml
index 506efe9bfa1..99e95fff5a2 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbits.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbits.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: fluentbits.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
@@ -610,8 +610,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -1183,7 +1183,9 @@ spec:
a Container.
properties:
name:
- description: Name of the environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1241,6 +1243,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1391,8 +1430,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1450,6 +1490,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1510,8 +1587,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -1538,8 +1615,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -2210,7 +2288,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2264,10 +2342,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -2279,6 +2357,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -3707,15 +3838,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -3896,12 +4025,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details Glusterfs
+ topology.
type: string
path:
description: |-
@@ -3980,7 +4107,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -4392,6 +4519,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be addressed
+ to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -4526,7 +4758,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
@@ -5019,7 +5250,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6055,15 +6286,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -6245,12 +6474,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -6329,7 +6556,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -6749,6 +6976,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -6883,7 +7215,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_multilineparsers.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_multilineparsers.yaml
index ec684d1414c..be64ff720a4 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_multilineparsers.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_multilineparsers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: multilineparsers.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_outputs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_outputs.yaml
index 830a88f558e..7da1e0b4203 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_outputs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_outputs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: outputs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_parsers.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_parsers.yaml
index 9d6c5136586..6bfe5e95284 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_parsers.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_parsers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: parsers.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/example/seed-crds/10-crd-machine.sapcloud.io_machineclasses.yaml b/example/seed-crds/10-crd-machine.sapcloud.io_machineclasses.yaml
index fa3dffa06ec..9f7c5944e5f 100644
--- a/example/seed-crds/10-crd-machine.sapcloud.io_machineclasses.yaml
+++ b/example/seed-crds/10-crd-machine.sapcloud.io_machineclasses.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: machineclasses.machine.sapcloud.io
spec:
group: machine.sapcloud.io
diff --git a/example/seed-crds/10-crd-machine.sapcloud.io_machinedeployments.yaml b/example/seed-crds/10-crd-machine.sapcloud.io_machinedeployments.yaml
index 3f7b108ce82..de78891f050 100644
--- a/example/seed-crds/10-crd-machine.sapcloud.io_machinedeployments.yaml
+++ b/example/seed-crds/10-crd-machine.sapcloud.io_machinedeployments.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: machinedeployments.machine.sapcloud.io
spec:
group: machine.sapcloud.io
@@ -397,9 +397,8 @@ spec:
to a node.
type: string
timeAdded:
- description: |-
- TimeAdded represents the time at which the taint was added.
- It is only written for NoExecute taints.
+ description: TimeAdded represents the time at
+ which the taint was added.
format: date-time
type: string
value:
diff --git a/example/seed-crds/10-crd-machine.sapcloud.io_machines.yaml b/example/seed-crds/10-crd-machine.sapcloud.io_machines.yaml
index cb88e5b4bf9..60a719acf87 100644
--- a/example/seed-crds/10-crd-machine.sapcloud.io_machines.yaml
+++ b/example/seed-crds/10-crd-machine.sapcloud.io_machines.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: machines.machine.sapcloud.io
spec:
group: machine.sapcloud.io
@@ -194,9 +194,8 @@ spec:
a node.
type: string
timeAdded:
- description: |-
- TimeAdded represents the time at which the taint was added.
- It is only written for NoExecute taints.
+ description: TimeAdded represents the time at which
+ the taint was added.
format: date-time
type: string
value:
diff --git a/example/seed-crds/10-crd-machine.sapcloud.io_machinesets.yaml b/example/seed-crds/10-crd-machine.sapcloud.io_machinesets.yaml
index 531232ba1c2..185ff6f7e68 100644
--- a/example/seed-crds/10-crd-machine.sapcloud.io_machinesets.yaml
+++ b/example/seed-crds/10-crd-machine.sapcloud.io_machinesets.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: machinesets.machine.sapcloud.io
spec:
group: machine.sapcloud.io
@@ -279,9 +279,8 @@ spec:
to a node.
type: string
timeAdded:
- description: |-
- TimeAdded represents the time at which the taint was added.
- It is only written for NoExecute taints.
+ description: TimeAdded represents the time at
+ which the taint was added.
format: date-time
type: string
value:
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_alertmanagerconfigs.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_alertmanagerconfigs.yaml
index 0298bac64ca..88429306f60 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_alertmanagerconfigs.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_alertmanagerconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: alertmanagerconfigs.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_alertmanagers.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_alertmanagers.yaml
index c1319eb26a8..96fad4d0d5d 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_alertmanagers.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_alertmanagers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: alertmanagers.monitoring.coreos.com
spec:
group: monitoring.coreos.com
@@ -674,8 +674,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -2887,8 +2887,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -2946,6 +2947,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -3006,8 +3044,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -3034,8 +3072,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -3706,7 +3745,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3760,10 +3799,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -3775,6 +3814,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -4476,8 +4568,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -4535,6 +4628,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -4595,8 +4725,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -4623,8 +4753,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -5295,7 +5426,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -5349,10 +5480,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -5364,6 +5495,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -6009,7 +6193,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6597,15 +6781,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -6853,15 +7035,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -7023,13 +7203,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -8034,15 +8212,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -8224,12 +8400,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -8308,7 +8482,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -8728,6 +8902,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -8862,7 +9141,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_podmonitors.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_podmonitors.yaml
index 5aac7b91cce..c888967e7c4 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_podmonitors.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_podmonitors.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: podmonitors.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_probes.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_probes.yaml
index 0cc48a5bab3..4ac47e50aa1 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_probes.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_probes.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: probes.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_prometheusagents.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_prometheusagents.yaml
index 5d17a634635..74e741011b3 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_prometheusagents.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_prometheusagents.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: prometheusagents.monitoring.coreos.com
spec:
group: monitoring.coreos.com
@@ -705,8 +705,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -1510,8 +1510,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1569,6 +1570,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1629,8 +1667,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -1657,8 +1695,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -2329,7 +2368,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2383,10 +2422,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -2398,6 +2437,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -3337,8 +3429,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -3396,6 +3489,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -3456,8 +3586,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -3484,8 +3614,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -4156,7 +4287,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -4210,10 +4341,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -4225,6 +4356,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -6354,7 +6538,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -7736,15 +7920,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -7992,15 +8174,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -8162,13 +8342,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -9432,15 +9610,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -9622,12 +9798,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -9706,7 +9880,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -10126,6 +10300,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -10260,7 +10539,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_prometheuses.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_prometheuses.yaml
index 00768cd7ecc..c5420605b20 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_prometheuses.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_prometheuses.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: prometheuses.monitoring.coreos.com
spec:
group: monitoring.coreos.com
@@ -783,8 +783,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -2248,8 +2248,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -2307,6 +2308,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -2367,8 +2405,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -2395,8 +2433,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -3067,7 +3106,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3121,10 +3160,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -3136,6 +3175,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -4117,8 +4209,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -4176,6 +4269,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -4236,8 +4366,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -4264,8 +4394,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -4936,7 +5067,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -4990,10 +5121,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -5005,6 +5136,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -7920,7 +8104,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -9485,15 +9669,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -9741,15 +9923,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -9911,13 +10091,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -10304,7 +10482,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -11698,15 +11876,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -11888,12 +12064,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -11972,7 +12146,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -12392,6 +12566,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -12526,7 +12805,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_prometheusrules.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_prometheusrules.yaml
index 6e41ee48a8d..f4800ee9ed9 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_prometheusrules.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_prometheusrules.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: prometheusrules.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_scrapeconfigs.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_scrapeconfigs.yaml
index e9157384362..b6a61bb8bad 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_scrapeconfigs.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_scrapeconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: scrapeconfigs.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_servicemonitors.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_servicemonitors.yaml
index 0d868a6074e..5913993c581 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_servicemonitors.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_servicemonitors.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: servicemonitors.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/example/seed-crds/10-crd-monitoring.coreos.com_thanosrulers.yaml b/example/seed-crds/10-crd-monitoring.coreos.com_thanosrulers.yaml
index be079491bcd..2285730da9d 100644
--- a/example/seed-crds/10-crd-monitoring.coreos.com_thanosrulers.yaml
+++ b/example/seed-crds/10-crd-monitoring.coreos.com_thanosrulers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: thanosrulers.monitoring.coreos.com
spec:
group: monitoring.coreos.com
@@ -671,8 +671,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -1165,8 +1165,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1224,6 +1225,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1284,8 +1322,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -1312,8 +1350,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -1984,7 +2023,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2038,10 +2077,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -2053,6 +2092,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -2974,8 +3066,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -3033,6 +3126,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -3093,8 +3223,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -3121,8 +3251,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -3793,7 +3924,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3847,10 +3978,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -3862,6 +3993,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -5680,7 +5864,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6374,15 +6558,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -6630,15 +6812,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -6800,13 +6980,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -7850,15 +8028,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -8040,12 +8216,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -8124,7 +8298,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -8544,6 +8718,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -8678,7 +8957,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/example/seed-crds/10-crd-perses.dev_perses.yaml b/example/seed-crds/10-crd-perses.dev_perses.yaml
index 78ded4e5638..3a9e93b42ce 100644
--- a/example/seed-crds/10-crd-perses.dev_perses.yaml
+++ b/example/seed-crds/10-crd-perses.dev_perses.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: perses.perses.dev
spec:
group: perses.dev
@@ -610,8 +610,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
diff --git a/example/seed-crds/10-crd-perses.dev_persesdashboards.yaml b/example/seed-crds/10-crd-perses.dev_persesdashboards.yaml
index e88d62e47f1..301ea4eb0e6 100644
--- a/example/seed-crds/10-crd-perses.dev_persesdashboards.yaml
+++ b/example/seed-crds/10-crd-perses.dev_persesdashboards.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: persesdashboards.perses.dev
spec:
group: perses.dev
diff --git a/example/seed-crds/10-crd-perses.dev_persesdatasources.yaml b/example/seed-crds/10-crd-perses.dev_persesdatasources.yaml
index 07c4e8a0fef..4e4838af27b 100644
--- a/example/seed-crds/10-crd-perses.dev_persesdatasources.yaml
+++ b/example/seed-crds/10-crd-perses.dev_persesdatasources.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: persesdatasources.perses.dev
spec:
group: perses.dev
diff --git a/example/seed-crds/10-crd-resources.gardener.cloud_managedresources.yaml b/example/seed-crds/10-crd-resources.gardener.cloud_managedresources.yaml
index e24239b49bd..6ce5eeccc11 100644
--- a/example/seed-crds/10-crd-resources.gardener.cloud_managedresources.yaml
+++ b/example/seed-crds/10-crd-resources.gardener.cloud_managedresources.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: managedresources.resources.gardener.cloud
spec:
group: resources.gardener.cloud
diff --git a/extensions/pkg/controller/controlplane/genericactuator/actuator_test.go b/extensions/pkg/controller/controlplane/genericactuator/actuator_test.go
index 31924d909e8..97a49951d69 100644
--- a/extensions/pkg/controller/controlplane/genericactuator/actuator_test.go
+++ b/extensions/pkg/controller/controlplane/genericactuator/actuator_test.go
@@ -317,8 +317,7 @@ var _ = Describe("Actuator", func() {
if webhookConfig != nil {
compressedData, err := test.BrotliCompressionForManifests(`apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
-metadata:
- creationTimestamp: null
+metadata: {}
webhooks:
- admissionReviewVersions: null
clientConfig: {}
diff --git a/extensions/pkg/controller/worker/controller_test.go b/extensions/pkg/controller/worker/controller_test.go
index bde440cbad9..278ab079d5f 100644
--- a/extensions/pkg/controller/worker/controller_test.go
+++ b/extensions/pkg/controller/worker/controller_test.go
@@ -13,6 +13,8 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/event"
@@ -37,7 +39,10 @@ var _ = Describe("Controller", func() {
BeforeEach(func() {
ctx = context.Background()
- c = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
+ objectTracker := testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())
+ c = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithObjectTracker(objectTracker).Build()
machineDeployment = &machinev1alpha1.MachineDeployment{
ObjectMeta: metav1.ObjectMeta{
diff --git a/extensions/pkg/controller/worker/genericactuator/actuator_reconcile_test.go b/extensions/pkg/controller/worker/genericactuator/actuator_reconcile_test.go
index 896c26f0807..828155b4e47 100644
--- a/extensions/pkg/controller/worker/genericactuator/actuator_reconcile_test.go
+++ b/extensions/pkg/controller/worker/genericactuator/actuator_reconcile_test.go
@@ -12,6 +12,8 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -39,9 +41,12 @@ var _ = Describe("ActuatorReconcile", func() {
)
BeforeEach(func() {
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
seedClient = fakeclient.NewClientBuilder().
WithScheme(kubernetes.SeedScheme).
WithStatusSubresource(&extensionsv1alpha1.Worker{}, &machinev1alpha1.MachineDeployment{}).
+ WithObjectTracker(testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())).
Build()
ctx = context.Background()
@@ -171,9 +176,12 @@ var _ = Describe("ActuatorReconcile", func() {
)
BeforeEach(func() {
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
seedClient = fakeclient.NewClientBuilder().
WithScheme(kubernetes.SeedScheme).
WithStatusSubresource(&extensionsv1alpha1.Worker{}, &machinev1alpha1.MachineDeployment{}).
+ WithObjectTracker(testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())).
Build()
ctx = context.Background()
diff --git a/go.mod b/go.mod
index 2cd653a7fba..6402cf360d3 100644
--- a/go.mod
+++ b/go.mod
@@ -62,31 +62,30 @@ require (
helm.sh/helm/v3 v3.18.6
istio.io/api v1.27.3
istio.io/client-go v1.27.2
- k8s.io/api v0.33.5
- k8s.io/apiextensions-apiserver v0.33.5
- k8s.io/apimachinery v0.33.5
- k8s.io/apiserver v0.33.5
+ k8s.io/api v0.34.1
+ k8s.io/apiextensions-apiserver v0.34.1
+ k8s.io/apimachinery v0.34.1
+ k8s.io/apiserver v0.34.1
// TODO(vitanovs): Update k8s.io/autoscaler/vertical-pod-autoscaler to v1.5.1 once https://github.com/gardener/gardener/issues/13162 is resolved.
k8s.io/autoscaler/vertical-pod-autoscaler v1.4.2
- k8s.io/cli-runtime v0.33.5
- k8s.io/client-go v0.33.5
- k8s.io/cluster-bootstrap v0.33.5
- k8s.io/code-generator v0.33.5
- k8s.io/component-base v0.33.5
- k8s.io/component-helpers v0.33.5
+ k8s.io/cli-runtime v0.34.1
+ k8s.io/client-go v0.34.1
+ k8s.io/cluster-bootstrap v0.34.1
+ k8s.io/code-generator v0.34.1
+ k8s.io/component-base v0.34.1
+ k8s.io/component-helpers v0.34.1
k8s.io/klog/v2 v2.130.1
- k8s.io/kube-aggregator v0.33.5
- k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911
- k8s.io/kube-proxy v0.33.5
+ k8s.io/kube-aggregator v0.34.1
+ k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b
+ k8s.io/kube-proxy v0.34.1
k8s.io/kube-state-metrics/v2 v2.13.0
- k8s.io/kubelet v0.33.5
- k8s.io/metrics v0.33.5
- k8s.io/pod-security-admission v0.33.5
+ k8s.io/kubelet v0.34.1
+ k8s.io/metrics v0.34.1
+ k8s.io/pod-security-admission v0.34.1
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4
- sigs.k8s.io/controller-runtime v0.21.0
- sigs.k8s.io/controller-tools v0.18.0
- sigs.k8s.io/structured-merge-diff/v4 v4.7.0
- sigs.k8s.io/yaml v1.5.0
+ sigs.k8s.io/controller-runtime v0.22.3
+ sigs.k8s.io/controller-tools v0.19.0
+ sigs.k8s.io/yaml v1.6.0
)
require (
@@ -136,7 +135,7 @@ require (
github.com/fatih/color v1.18.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
- github.com/fxamacker/cbor/v2 v2.8.0 // indirect
+ github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/errors v0.22.0 // indirect
@@ -152,7 +151,7 @@ require (
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect
- github.com/google/cel-go v0.25.0 // indirect
+ github.com/google/cel-go v0.26.0 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/gorilla/handlers v1.5.2 // indirect
github.com/gorilla/mux v1.8.1 // indirect
@@ -191,7 +190,7 @@ require (
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
- github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/muhlemmer/gu v0.3.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
@@ -204,6 +203,7 @@ require (
github.com/perses/common v0.27.1-0.20250326140707-96e439b14e0e // indirect
github.com/perses/perses v0.51.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/otlptranslator v0.0.2 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
@@ -226,15 +226,15 @@ require (
github.com/x448/float16 v0.8.4 // indirect
github.com/zitadel/oidc/v3 v3.38.1 // indirect
github.com/zitadel/schema v1.3.1 // indirect
- go.etcd.io/etcd/api/v3 v3.5.21 // indirect
- go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect
- go.etcd.io/etcd/client/v3 v3.5.21 // indirect
+ go.etcd.io/etcd/api/v3 v3.6.4 // indirect
+ go.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect
+ go.etcd.io/etcd/client/v3 v3.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/collector/featuregate v1.37.0 // indirect
go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 // indirect
go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect
go.opentelemetry.io/contrib/otelconf v0.18.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
@@ -276,12 +276,13 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect
- k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 // indirect
+ k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect
k8s.io/klog v1.0.0 // indirect
- k8s.io/kms v0.33.5 // indirect
+ k8s.io/kms v0.34.1 // indirect
k8s.io/sample-controller v0.30.3 // indirect
oras.land/oras-go/v2 v2.6.0 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
+ sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
)
diff --git a/go.sum b/go.sum
index 3cb4f90db88..3b8452fd296 100644
--- a/go.sum
+++ b/go.sum
@@ -234,8 +234,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
-github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
-github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
+github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
+github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gardener/cert-management v0.18.0 h1:s2YhkN8z7lXe9En52GCeqQ9be10uEbLtH/FFAh6BVgQ=
github.com/gardener/cert-management v0.18.0/go.mod h1:9+JT+EBJB2OIX65EG+P1p/DZ/UJ3W8WR0h40ZjKbw+Q=
github.com/gardener/dependency-watchdog v1.6.0 h1:ARCIbcNmhjefmV7ex8ADReeD2MPsEawwT/MoZKTQV/M=
@@ -310,8 +310,6 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
-github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
-github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -342,8 +340,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
-github.com/google/cel-go v0.25.0 h1:jsFw9Fhn+3y2kBbltZR4VEz5xKkcIFRPDnuEzAGv5GY=
-github.com/google/cel-go v0.25.0/go.mod h1:hjEb6r5SuOSlhCHmFoLzu8HGCERvIsDAbxDAyNU/MmI=
+github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI=
+github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -396,11 +394,12 @@ github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrR
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
-github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
+github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
+github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
+github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs=
+github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
github.com/hashicorp/consul/api v1.30.0 h1:ArHVMMILb1nQv8vZSGIwwQd2gtc+oSQZ6CalyiyH2XQ=
@@ -451,8 +450,8 @@ github.com/ironcore-dev/vgopath v0.1.5 h1:+I46zEFfbmNIGIGylqedT2bMXw8V7yVP16GJkG
github.com/ironcore-dev/vgopath v0.1.5/go.mod h1:qbSUA7Eg0SO97OYfkG0DH+DxaPrH6XCiAQHqqs9R63Q=
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY=
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
-github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
-github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
+github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
+github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE=
@@ -547,8 +546,9 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
+github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM=
github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
@@ -749,22 +749,20 @@ github.com/zitadel/oidc/v3 v3.38.1 h1:VTf1Bv/33UbSwJnIWbfEIdpUGYKfoHetuBNIqVTcjv
github.com/zitadel/oidc/v3 v3.38.1/go.mod h1:muukzAasaWmn3vBwEVMglJfuTE0PKCvLJGombPwXIRw=
github.com/zitadel/schema v1.3.1 h1:QT3kwiRIRXXLVAs6gCK/u044WmUVh6IlbLXUsn6yRQU=
github.com/zitadel/schema v1.3.1/go.mod h1:071u7D2LQacy1HAN+YnMd/mx1qVE2isb0Mjeqg46xnU=
-go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
-go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
-go.etcd.io/etcd/api/v3 v3.5.21 h1:A6O2/JDb3tvHhiIz3xf9nJ7REHvtEFJJ3veW3FbCnS8=
-go.etcd.io/etcd/api/v3 v3.5.21/go.mod h1:c3aH5wcvXv/9dqIw2Y810LDXJfhSYdHQ0vxmP3CCHVY=
-go.etcd.io/etcd/client/pkg/v3 v3.5.21 h1:lPBu71Y7osQmzlflM9OfeIV2JlmpBjqBNlLtcoBqUTc=
-go.etcd.io/etcd/client/pkg/v3 v3.5.21/go.mod h1:BgqT/IXPjK9NkeSDjbzwsHySX3yIle2+ndz28nVsjUs=
-go.etcd.io/etcd/client/v2 v2.305.21 h1:eLiFfexc2mE+pTLz9WwnoEsX5JTTpLCYVivKkmVXIRA=
-go.etcd.io/etcd/client/v2 v2.305.21/go.mod h1:OKkn4hlYNf43hpjEM3Ke3aRdUkhSl8xjKjSf8eCq2J8=
-go.etcd.io/etcd/client/v3 v3.5.21 h1:T6b1Ow6fNjOLOtM0xSoKNQt1ASPCLWrF9XMHcH9pEyY=
-go.etcd.io/etcd/client/v3 v3.5.21/go.mod h1:mFYy67IOqmbRf/kRUvsHixzo3iG+1OF2W2+jVIQRAnU=
-go.etcd.io/etcd/pkg/v3 v3.5.21 h1:jUItxeKyrDuVuWhdh0HtjUANwyuzcb7/FAeUfABmQsk=
-go.etcd.io/etcd/pkg/v3 v3.5.21/go.mod h1:wpZx8Egv1g4y+N7JAsqi2zoUiBIUWznLjqJbylDjWgU=
-go.etcd.io/etcd/raft/v3 v3.5.21 h1:dOmE0mT55dIUsX77TKBLq+RgyumsQuYeiRQnW/ylugk=
-go.etcd.io/etcd/raft/v3 v3.5.21/go.mod h1:fmcuY5R2SNkklU4+fKVBQi2biVp5vafMrWUEj4TJ4Cs=
-go.etcd.io/etcd/server/v3 v3.5.21 h1:9w0/k12majtgarGmlMVuhwXRI2ob3/d1Ik3X5TKo0yU=
-go.etcd.io/etcd/server/v3 v3.5.21/go.mod h1:G1mOzdwuzKT1VRL7SqRchli/qcFrtLBTAQ4lV20sXXo=
+go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I=
+go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM=
+go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo=
+go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk=
+go.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0=
+go.etcd.io/etcd/client/pkg/v3 v3.6.4/go.mod h1:sbdzr2cl3HzVmxNw//PH7aLGVtY4QySjQFuaCgcRFAI=
+go.etcd.io/etcd/client/v3 v3.6.4 h1:YOMrCfMhRzY8NgtzUsHl8hC2EBSnuqbR3dh84Uryl7A=
+go.etcd.io/etcd/client/v3 v3.6.4/go.mod h1:jaNNHCyg2FdALyKWnd7hxZXZxZANb0+KGY+YQaEMISo=
+go.etcd.io/etcd/pkg/v3 v3.6.4 h1:fy8bmXIec1Q35/jRZ0KOes8vuFxbvdN0aAFqmEfJZWA=
+go.etcd.io/etcd/pkg/v3 v3.6.4/go.mod h1:kKcYWP8gHuBRcteyv6MXWSN0+bVMnfgqiHueIZnKMtE=
+go.etcd.io/etcd/server/v3 v3.6.4 h1:LsCA7CzjVt+8WGrdsnh6RhC0XqCsLkBly3ve5rTxMAU=
+go.etcd.io/etcd/server/v3 v3.6.4/go.mod h1:aYCL/h43yiONOv0QIR82kH/2xZ7m+IWYjzRmyQfnCAg=
+go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ=
+go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -778,8 +776,8 @@ go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 h1:UW0+QyeyBVhn+COBec3nGh
go.opentelemetry.io/contrib/bridges/prometheus v0.57.0/go.mod h1:ppciCHRLsyCio54qbzQv0E4Jyth/fLWDTJYfvWpcSVk=
go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQa2NQ/Aoi7zA+wy7vMOKD9H4=
go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY=
go.opentelemetry.io/contrib/otelconf v0.18.0 h1:ciF2Gf00BWs0DnexKFZXcxg9kJ8r3SUW1LOzW3CsKA8=
@@ -1087,38 +1085,38 @@ istio.io/api v1.27.3/go.mod h1:DTVGH6CLXj5W8FF9JUD3Tis78iRgT1WeuAnxfTz21Wg=
istio.io/client-go v1.27.2 h1:4IsF7UAdV5Yg0iq6ONyWZpjFr3z2ahkIbLWyzOHCAwA=
istio.io/client-go v1.27.2/go.mod h1:zgT5R1USl6rwYK1eb2kisPuiji05TQJE7CQHU253iAg=
k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw=
-k8s.io/api v0.33.5 h1:YR+uhYj05jdRpcksv8kjSliW+v9hwXxn6Cv10aR8Juw=
-k8s.io/api v0.33.5/go.mod h1:2gzShdwXKT5yPGiqrTrn/U/nLZ7ZyT4WuAj3XGDVgVs=
-k8s.io/apiextensions-apiserver v0.33.5 h1:93NZh6rmrcamX/tfv/dZrTsMiQX69ufANmDcKPEgSeA=
-k8s.io/apiextensions-apiserver v0.33.5/go.mod h1:JIbyQnNlu6nQa7b1vgFi51pmlXOk8mdn0WJwUJnz/7U=
+k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM=
+k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk=
+k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI=
+k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc=
k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
-k8s.io/apimachinery v0.33.5 h1:NiT64hln4TQXeYR18/ES39OrNsjGz8NguxsBgp+6QIo=
-k8s.io/apimachinery v0.33.5/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
-k8s.io/apiserver v0.33.5 h1:X1Gy33r4YkRLRqTjGjofk7X1/EjSLEVSJ/A+1qjoj60=
-k8s.io/apiserver v0.33.5/go.mod h1:Q+b5Btbc8x0PqOCeh/xBTesKk+cXQRN+PF2wdrTKDeg=
+k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4=
+k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
+k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA=
+k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0=
k8s.io/autoscaler/vertical-pod-autoscaler v1.4.2 h1:47RLgLhrxXfdBchTeNT2S9Xe9o+Y4kThExLfcGGUQMk=
k8s.io/autoscaler/vertical-pod-autoscaler v1.4.2/go.mod h1:rIBiAf+sK2mw8ryeHIZuY5juhJ4e2rNLwo59SDRXF7I=
-k8s.io/cli-runtime v0.33.5 h1:wM7DoglOkrJDmddla864mVpueaEDX7/XGAkHGMWQkpc=
-k8s.io/cli-runtime v0.33.5/go.mod h1:ZmUR+ybq97SqxSkkqGQdIhzCfk/+ETUhwKQq5EguaCw=
+k8s.io/cli-runtime v0.34.1 h1:btlgAgTrYd4sk8vJTRG6zVtqBKt9ZMDeQZo2PIzbL7M=
+k8s.io/cli-runtime v0.34.1/go.mod h1:aVA65c+f0MZiMUPbseU/M9l1Wo2byeaGwUuQEQVVveE=
k8s.io/client-go v0.19.0/go.mod h1:H9E/VT95blcFQnlyShFgnFT9ZnJOAceiUHM3MlRC+mU=
-k8s.io/client-go v0.33.5 h1:I8BdmQGxInpkMEnJvV6iG7dqzP3JRlpZZlib3OMFc3o=
-k8s.io/client-go v0.33.5/go.mod h1:W8PQP4MxbM4ypgagVE65mUUqK1/ByQkSALF9tzuQ6u0=
-k8s.io/cluster-bootstrap v0.33.5 h1:VO0BhAwtAa6PYbBTkpK6mZwkGs8dlbeAN8pXbEovWWw=
-k8s.io/cluster-bootstrap v0.33.5/go.mod h1:jPhTDgjG8RfxGkNJQzt3Qffq/KcYGRJI+UbKeJvEFyw=
+k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY=
+k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8=
+k8s.io/cluster-bootstrap v0.34.1 h1:lyCwJKoeYzGI93vk5Sn/Gz2rzfTRXkRuZYOk2rUsHfA=
+k8s.io/cluster-bootstrap v0.34.1/go.mod h1:9EJfkp7Fu4YBU0F6ysvrI5TndWLo8zufmDSjIWBNd94=
k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk=
-k8s.io/code-generator v0.33.5 h1:KwkOvhwAaorjSwF2MQhhdhL3i8bBmAal/TWhX67kdHw=
-k8s.io/code-generator v0.33.5/go.mod h1:Ra+sdZquRakeTGcEnQAPw6BmlZ92IvxwQQTX/XOvOIE=
-k8s.io/component-base v0.33.5 h1:4D3kxjEx1pJRy3WHAZsmX3+LCpmd4ftE+2J4v6naTnQ=
-k8s.io/component-base v0.33.5/go.mod h1:Zma1YjBVuuGxIbspj1vGR3/5blzo2ARf1v0QTtog1to=
-k8s.io/component-helpers v0.33.5 h1:1LDSMzn7YTreVLPaOBJK36ase/FWi2sDpeJJvbEBO2s=
-k8s.io/component-helpers v0.33.5/go.mod h1:C3HsDU2lANSLgTTgMJ0TFnG5xZrVrxR3Ss9n7Wrsw4s=
+k8s.io/code-generator v0.34.1 h1:WpphT26E+j7tEgIUfFr5WfbJrktCGzB3JoJH9149xYc=
+k8s.io/code-generator v0.34.1/go.mod h1:DeWjekbDnJWRwpw3s0Jat87c+e0TgkxoR4ar608yqvg=
+k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A=
+k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0=
+k8s.io/component-helpers v0.34.1 h1:gWhH3CCdwAx5P3oJqZKb4Lg5FYZTWVbdWtOI8n9U4XY=
+k8s.io/component-helpers v0.34.1/go.mod h1:4VgnUH7UA/shuBur+OWoQC0xfb69sy/93ss0ybZqm3c=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks=
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
-k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1PoqTlYqEq5H2oetog=
-k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
+k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f h1:SLb+kxmzfA87x4E4brQzB33VBbT2+x7Zq9ROIHmGn9Q=
+k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
@@ -1126,23 +1124,23 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
-k8s.io/kms v0.33.5 h1:u60sDBe4Fz6PLeiNF13sEahjIU428ajiWuIw7NSVBlg=
-k8s.io/kms v0.33.5/go.mod h1:C1I8mjFFBNzfUZXYt9FZVJ8MJl7ynFbGgZFbBzkBJ3E=
-k8s.io/kube-aggregator v0.33.5 h1:5libMG9e4m9lwhNBT89bBCd9x/rZebMahw5CHq9DE/Q=
-k8s.io/kube-aggregator v0.33.5/go.mod h1:mHmmDqxY2ZkInu7eSAXb1ecaKV/U9DqPTQWBV2O84go=
+k8s.io/kms v0.34.1 h1:iCFOvewDPzWM9fMTfyIPO+4MeuZ0tcZbugxLNSHFG4w=
+k8s.io/kms v0.34.1/go.mod h1:s1CFkLG7w9eaTYvctOxosx88fl4spqmixnNpys0JAtM=
+k8s.io/kube-aggregator v0.34.1 h1:WNLV0dVNoFKmuyvdWLd92iDSyD/TSTjqwaPj0U9XAEU=
+k8s.io/kube-aggregator v0.34.1/go.mod h1:RU8j+5ERfp0h+gIvWtxRPfsa5nK7rboDm8RST8BJfYQ=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
-k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 h1:gAXU86Fmbr/ktY17lkHwSjw5aoThQvhnstGGIYKlKYc=
-k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911/go.mod h1:GLOk5B+hDbRROvt0X2+hqX64v/zO3vXN7J78OUmBSKw=
-k8s.io/kube-proxy v0.33.5 h1:wgzKB5pkDl8hlRQTE+Va5t9DTu40UZJGhIrWod/id90=
-k8s.io/kube-proxy v0.33.5/go.mod h1:w7tesj0OkcF8UVFRSv8Ja1ohYrGgGcAmandGqB+orz0=
+k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=
+k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
+k8s.io/kube-proxy v0.34.1 h1:cIriNCJY5XmRhXCCyQiazyqi47lbwcBQf0H76fVOpkw=
+k8s.io/kube-proxy v0.34.1/go.mod h1:syed9c5+gUVFMo6p24SnlTHzsp+BMd4ACcTw2dbArw0=
k8s.io/kube-state-metrics/v2 v2.13.0 h1:g5OV0cwrDKvyrQApYxI7Ny+vFUgU3X6MYrnIzdCAdNU=
k8s.io/kube-state-metrics/v2 v2.13.0/go.mod h1:sGt/NFkZkA4hqb4cVd/xG2G17dzZ72TQXqSpHn8rF/U=
-k8s.io/kubelet v0.33.5 h1:PYV+O8B6ZoQMDaQdYTSCzNdQTLdjAAWTspS2KkNfjLQ=
-k8s.io/kubelet v0.33.5/go.mod h1:8SQ/0fgyNwm6zjHktBhPAUlgtji19YMa2lhSlYKUhrA=
-k8s.io/metrics v0.33.5 h1:dOG+Yh4SZ6TJ7LcjvVXrYFvZ9G+sogCpTWyhoOVgQCE=
-k8s.io/metrics v0.33.5/go.mod h1:YvBlRD01hos/j7dmjdtSBaZbmGyCJrxVS977x5+Y1kk=
-k8s.io/pod-security-admission v0.33.5 h1:wThuFFa3ykpClGqtjRKEn/7zaIuinvvqgpzPdHPVwOs=
-k8s.io/pod-security-admission v0.33.5/go.mod h1:hlFjlok9N9X94rqbG3/xNU1m4V4hiuANvlIk/lL9hXE=
+k8s.io/kubelet v0.34.1 h1:doAaTA9/Yfzbdq/u/LveZeONp96CwX9giW6b+oHn4m4=
+k8s.io/kubelet v0.34.1/go.mod h1:PtV3Ese8iOM19gSooFoQT9iyRisbmJdAPuDImuccbbA=
+k8s.io/metrics v0.34.1 h1:374Rexmp1xxgRt64Bi0TsjAM8cA/Y8skwCoPdjtIslE=
+k8s.io/metrics v0.34.1/go.mod h1:Drf5kPfk2NJrlpcNdSiAAHn/7Y9KqxpRNagByM7Ei80=
+k8s.io/pod-security-admission v0.34.1 h1:XsP5eh8qCj69hK0a5TBMU4Ed7Ckn8JEmmbk/iepj+XM=
+k8s.io/pod-security-admission v0.34.1/go.mod h1:87yY36Gxc8Hjx24FxqAD5zMY4k0tP0u7Mu/XuwXEbmg=
k8s.io/sample-controller v0.30.3 h1:oZTxERF8U3gANT2H5VxpkW32asgmW0IYGyUv9Opspvs=
k8s.io/sample-controller v0.30.3/go.mod h1:yhy/cWCzevQLa2+7Gvj0J9+xzmNExypunffSNANBy7o=
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
@@ -1153,22 +1151,20 @@ oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
-sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
-sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
-sigs.k8s.io/controller-tools v0.18.0 h1:rGxGZCZTV2wJreeRgqVoWab/mfcumTMmSwKzoM9xrsE=
-sigs.k8s.io/controller-tools v0.18.0/go.mod h1:gLKoiGBriyNh+x1rWtUQnakUYEujErjXs9pf+x/8n1U=
+sigs.k8s.io/controller-runtime v0.22.3 h1:I7mfqz/a/WdmDCEnXmSPm8/b/yRTy6JsKKENTijTq8Y=
+sigs.k8s.io/controller-runtime v0.22.3/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
+sigs.k8s.io/controller-tools v0.19.0 h1:OU7jrPPiZusryu6YK0jYSjPqg8Vhf8cAzluP9XGI5uk=
+sigs.k8s.io/controller-tools v0.19.0/go.mod h1:y5HY/iNDFkmFla2CfQoVb2AQXMsBk4ad84iR1PLANB0=
sigs.k8s.io/gateway-api v1.3.0 h1:q6okN+/UKDATola4JY7zXzx40WO4VISk7i9DIfOvr9M=
sigs.k8s.io/gateway-api v1.3.0/go.mod h1:d8NV8nJbaRbEKem+5IuxkL8gJGOZ+FJ+NvOIltV8gDk=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
-sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
-sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
-sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
+sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
+sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
-sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
-sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=
+sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
+sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
diff --git a/pkg/api/extensions/accessor_test.go b/pkg/api/extensions/accessor_test.go
index 29bfc756b0f..299a286dc76 100644
--- a/pkg/api/extensions/accessor_test.go
+++ b/pkg/api/extensions/accessor_test.go
@@ -92,7 +92,7 @@ var _ = Describe("Accessor", func() {
)
Expect(acc.GetProviderConfig()).To(Equal(&runtime.RawExtension{
- Raw: []byte(`{"metadata":{"creationTimestamp":null}}`),
+ Raw: []byte(`{"metadata":{}}`),
}))
})
@@ -115,7 +115,7 @@ var _ = Describe("Accessor", func() {
)
Expect(acc.GetProviderStatus()).To(Equal(&runtime.RawExtension{
- Raw: []byte(`{"metadata":{"creationTimestamp":null}}`),
+ Raw: []byte(`{"metadata":{}}`),
}))
})
diff --git a/pkg/apis/seedmanagement/v1alpha1/zz_generated.defaults.go b/pkg/apis/seedmanagement/v1alpha1/zz_generated.defaults.go
index d58cab329b4..021fdabe1ec 100644
--- a/pkg/apis/seedmanagement/v1alpha1/zz_generated.defaults.go
+++ b/pkg/apis/seedmanagement/v1alpha1/zz_generated.defaults.go
@@ -78,6 +78,17 @@ func SetObjectDefaults_Gardenlet(in *Gardenlet) {
}
}
}
+ for i := range in.Spec.Deployment.GardenletDeployment.Env {
+ a := &in.Spec.Deployment.GardenletDeployment.Env[i]
+ if a.ValueFrom != nil {
+ if a.ValueFrom.FileKeyRef != nil {
+ if a.ValueFrom.FileKeyRef.Optional == nil {
+ var ptrVar1 bool = false
+ a.ValueFrom.FileKeyRef.Optional = &ptrVar1
+ }
+ }
+ }
+ }
}
func SetObjectDefaults_GardenletList(in *GardenletList) {
@@ -139,6 +150,17 @@ func SetObjectDefaults_ManagedSeed(in *ManagedSeed) {
}
}
}
+ for i := range in.Spec.Gardenlet.Deployment.Env {
+ a := &in.Spec.Gardenlet.Deployment.Env[i]
+ if a.ValueFrom != nil {
+ if a.ValueFrom.FileKeyRef != nil {
+ if a.ValueFrom.FileKeyRef.Optional == nil {
+ var ptrVar1 bool = false
+ a.ValueFrom.FileKeyRef.Optional = &ptrVar1
+ }
+ }
+ }
+ }
}
}
@@ -201,6 +223,17 @@ func SetObjectDefaults_ManagedSeedSet(in *ManagedSeedSet) {
}
}
}
+ for i := range in.Spec.Template.Spec.Gardenlet.Deployment.Env {
+ a := &in.Spec.Template.Spec.Gardenlet.Deployment.Env[i]
+ if a.ValueFrom != nil {
+ if a.ValueFrom.FileKeyRef != nil {
+ if a.ValueFrom.FileKeyRef.Optional == nil {
+ var ptrVar1 bool = false
+ a.ValueFrom.FileKeyRef.Optional = &ptrVar1
+ }
+ }
+ }
+ }
}
if in.Spec.UpdateStrategy != nil {
SetDefaults_UpdateStrategy(in.Spec.UpdateStrategy)
diff --git a/pkg/apiserver/openapi/openapi_generated.go b/pkg/apiserver/openapi/openapi_generated.go
index 290f0a1f49f..a8e2442480a 100644
--- a/pkg/apiserver/openapi/openapi_generated.go
+++ b/pkg/apiserver/openapi/openapi_generated.go
@@ -329,9 +329,12 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"k8s.io/api/core/v1.ConfigMapProjection": schema_k8sio_api_core_v1_ConfigMapProjection(ref),
"k8s.io/api/core/v1.ConfigMapVolumeSource": schema_k8sio_api_core_v1_ConfigMapVolumeSource(ref),
"k8s.io/api/core/v1.Container": schema_k8sio_api_core_v1_Container(ref),
+ "k8s.io/api/core/v1.ContainerExtendedResourceRequest": schema_k8sio_api_core_v1_ContainerExtendedResourceRequest(ref),
"k8s.io/api/core/v1.ContainerImage": schema_k8sio_api_core_v1_ContainerImage(ref),
"k8s.io/api/core/v1.ContainerPort": schema_k8sio_api_core_v1_ContainerPort(ref),
"k8s.io/api/core/v1.ContainerResizePolicy": schema_k8sio_api_core_v1_ContainerResizePolicy(ref),
+ "k8s.io/api/core/v1.ContainerRestartRule": schema_k8sio_api_core_v1_ContainerRestartRule(ref),
+ "k8s.io/api/core/v1.ContainerRestartRuleOnExitCodes": schema_k8sio_api_core_v1_ContainerRestartRuleOnExitCodes(ref),
"k8s.io/api/core/v1.ContainerState": schema_k8sio_api_core_v1_ContainerState(ref),
"k8s.io/api/core/v1.ContainerStateRunning": schema_k8sio_api_core_v1_ContainerStateRunning(ref),
"k8s.io/api/core/v1.ContainerStateTerminated": schema_k8sio_api_core_v1_ContainerStateTerminated(ref),
@@ -360,6 +363,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"k8s.io/api/core/v1.EventSource": schema_k8sio_api_core_v1_EventSource(ref),
"k8s.io/api/core/v1.ExecAction": schema_k8sio_api_core_v1_ExecAction(ref),
"k8s.io/api/core/v1.FCVolumeSource": schema_k8sio_api_core_v1_FCVolumeSource(ref),
+ "k8s.io/api/core/v1.FileKeySelector": schema_k8sio_api_core_v1_FileKeySelector(ref),
"k8s.io/api/core/v1.FlexPersistentVolumeSource": schema_k8sio_api_core_v1_FlexPersistentVolumeSource(ref),
"k8s.io/api/core/v1.FlexVolumeSource": schema_k8sio_api_core_v1_FlexVolumeSource(ref),
"k8s.io/api/core/v1.FlockerVolumeSource": schema_k8sio_api_core_v1_FlockerVolumeSource(ref),
@@ -435,10 +439,12 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"k8s.io/api/core/v1.PodAffinityTerm": schema_k8sio_api_core_v1_PodAffinityTerm(ref),
"k8s.io/api/core/v1.PodAntiAffinity": schema_k8sio_api_core_v1_PodAntiAffinity(ref),
"k8s.io/api/core/v1.PodAttachOptions": schema_k8sio_api_core_v1_PodAttachOptions(ref),
+ "k8s.io/api/core/v1.PodCertificateProjection": schema_k8sio_api_core_v1_PodCertificateProjection(ref),
"k8s.io/api/core/v1.PodCondition": schema_k8sio_api_core_v1_PodCondition(ref),
"k8s.io/api/core/v1.PodDNSConfig": schema_k8sio_api_core_v1_PodDNSConfig(ref),
"k8s.io/api/core/v1.PodDNSConfigOption": schema_k8sio_api_core_v1_PodDNSConfigOption(ref),
"k8s.io/api/core/v1.PodExecOptions": schema_k8sio_api_core_v1_PodExecOptions(ref),
+ "k8s.io/api/core/v1.PodExtendedResourceClaimStatus": schema_k8sio_api_core_v1_PodExtendedResourceClaimStatus(ref),
"k8s.io/api/core/v1.PodIP": schema_k8sio_api_core_v1_PodIP(ref),
"k8s.io/api/core/v1.PodList": schema_k8sio_api_core_v1_PodList(ref),
"k8s.io/api/core/v1.PodLogOptions": schema_k8sio_api_core_v1_PodLogOptions(ref),
@@ -13888,6 +13894,7 @@ func schema_k8sio_api_autoscaling_v1_ScaleSpec(ref common.ReferenceCallback) com
"replicas": {
SchemaProps: spec.SchemaProps{
Description: "replicas is the desired number of instances for the scaled object.",
+ Default: 0,
Type: []string{"integer"},
Format: "int32",
},
@@ -15410,7 +15417,7 @@ func schema_k8sio_api_core_v1_Container(ref common.ReferenceCallback) common.Ope
},
},
SchemaProps: spec.SchemaProps{
- Description: "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
+ Description: "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
@@ -15474,11 +15481,30 @@ func schema_k8sio_api_core_v1_Container(ref common.ReferenceCallback) common.Ope
},
"restartPolicy": {
SchemaProps: spec.SchemaProps{
- Description: "RestartPolicy defines the restart behavior of individual containers in a pod. This field may only be set for init containers, and the only allowed value is \"Always\". For non-init containers or when this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. Setting the RestartPolicy as \"Always\" for the init container will have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy \"Always\" will be shut down. This lifecycle differs from normal init containers and is often referred to as a \"sidecar\" container. Although this init container still starts in the init container sequence, it does not wait for the container to complete before proceeding to the next init container. Instead, the next init container starts immediately after this init container is started, or after any startupProbe has successfully completed.",
+ Description: "RestartPolicy defines the restart behavior of individual containers in a pod. This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. Additionally, setting the RestartPolicy as \"Always\" for the init container will have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy \"Always\" will be shut down. This lifecycle differs from normal init containers and is often referred to as a \"sidecar\" container. Although this init container still starts in the init container sequence, it does not wait for the container to complete before proceeding to the next init container. Instead, the next init container starts immediately after this init container is started, or after any startupProbe has successfully completed.",
Type: []string{"string"},
Format: "",
},
},
+ "restartPolicyRules": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "atomic",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Description: "Represents a list of rules to be checked to determine if the container should be restarted on exit. The rules are evaluated in order. Once a rule matches a container exit condition, the remaining rules are ignored. If no rule matches the container exit condition, the Container-level restart policy determines the whether the container is restarted or not. Constraints on the rules: - At most 20 rules are allowed. - Rules can have the same action. - Identical rules are not forbidden in validations. When rules are specified, container MUST set RestartPolicy explicitly even it if matches the Pod's RestartPolicy.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/api/core/v1.ContainerRestartRule"),
+ },
+ },
+ },
+ },
+ },
"volumeMounts": {
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
@@ -15606,7 +15632,45 @@ func schema_k8sio_api_core_v1_Container(ref common.ReferenceCallback) common.Ope
},
},
Dependencies: []string{
- "k8s.io/api/core/v1.ContainerPort", "k8s.io/api/core/v1.ContainerResizePolicy", "k8s.io/api/core/v1.EnvFromSource", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.Lifecycle", "k8s.io/api/core/v1.Probe", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.SecurityContext", "k8s.io/api/core/v1.VolumeDevice", "k8s.io/api/core/v1.VolumeMount"},
+ "k8s.io/api/core/v1.ContainerPort", "k8s.io/api/core/v1.ContainerResizePolicy", "k8s.io/api/core/v1.ContainerRestartRule", "k8s.io/api/core/v1.EnvFromSource", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.Lifecycle", "k8s.io/api/core/v1.Probe", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.SecurityContext", "k8s.io/api/core/v1.VolumeDevice", "k8s.io/api/core/v1.VolumeMount"},
+ }
+}
+
+func schema_k8sio_api_core_v1_ContainerExtendedResourceRequest(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "ContainerExtendedResourceRequest has the mapping of container name, extended resource name to the device request name.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "containerName": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The name of the container requesting resources.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "resourceName": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The name of the extended resource in that container which gets backed by DRA.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "requestName": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The name of the request in the special ResourceClaim which corresponds to the extended resource.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"containerName", "resourceName", "requestName"},
+ },
+ },
}
}
@@ -15732,6 +15796,76 @@ func schema_k8sio_api_core_v1_ContainerResizePolicy(ref common.ReferenceCallback
}
}
+func schema_k8sio_api_core_v1_ContainerRestartRule(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "ContainerRestartRule describes how a container exit is handled.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "action": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Specifies the action taken on a container exit if the requirements are satisfied. The only possible value is \"Restart\" to restart the container.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "exitCodes": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Represents the exit codes to check on container exits.",
+ Ref: ref("k8s.io/api/core/v1.ContainerRestartRuleOnExitCodes"),
+ },
+ },
+ },
+ Required: []string{"action"},
+ },
+ },
+ Dependencies: []string{
+ "k8s.io/api/core/v1.ContainerRestartRuleOnExitCodes"},
+ }
+}
+
+func schema_k8sio_api_core_v1_ContainerRestartRuleOnExitCodes(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "ContainerRestartRuleOnExitCodes describes the condition for handling an exited container based on its exit codes.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "operator": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Represents the relationship between the container exit code(s) and the specified values. Possible values are: - In: the requirement is satisfied if the container exit code is in the\n set of specified values.\n- NotIn: the requirement is satisfied if the container exit code is\n not in the set of specified values.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "values": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "set",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Description: "Specifies the set of values to check for container exit codes. At most 255 elements are allowed.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int32",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"operator"},
+ },
+ },
+ }
+}
+
func schema_k8sio_api_core_v1_ContainerState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -16517,7 +16651,7 @@ func schema_k8sio_api_core_v1_EnvFromSource(ref common.ReferenceCallback) common
Properties: map[string]spec.Schema{
"prefix": {
SchemaProps: spec.SchemaProps{
- Description: "Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER.",
+ Description: "Optional text to prepend to the name of each environment variable. May consist of any printable ASCII characters except '='.",
Type: []string{"string"},
Format: "",
},
@@ -16551,7 +16685,7 @@ func schema_k8sio_api_core_v1_EnvVar(ref common.ReferenceCallback) common.OpenAP
Properties: map[string]spec.Schema{
"name": {
SchemaProps: spec.SchemaProps{
- Description: "Name of the environment variable. Must be a C_IDENTIFIER.",
+ Description: "Name of the environment variable. May consist of any printable ASCII characters except '='.",
Default: "",
Type: []string{"string"},
Format: "",
@@ -16610,11 +16744,17 @@ func schema_k8sio_api_core_v1_EnvVarSource(ref common.ReferenceCallback) common.
Ref: ref("k8s.io/api/core/v1.SecretKeySelector"),
},
},
+ "fileKeyRef": {
+ SchemaProps: spec.SchemaProps{
+ Description: "FileKeyRef selects a key of the env file. Requires the EnvFiles feature gate to be enabled.",
+ Ref: ref("k8s.io/api/core/v1.FileKeySelector"),
+ },
+ },
},
},
},
Dependencies: []string{
- "k8s.io/api/core/v1.ConfigMapKeySelector", "k8s.io/api/core/v1.ObjectFieldSelector", "k8s.io/api/core/v1.ResourceFieldSelector", "k8s.io/api/core/v1.SecretKeySelector"},
+ "k8s.io/api/core/v1.ConfigMapKeySelector", "k8s.io/api/core/v1.FileKeySelector", "k8s.io/api/core/v1.ObjectFieldSelector", "k8s.io/api/core/v1.ResourceFieldSelector", "k8s.io/api/core/v1.SecretKeySelector"},
}
}
@@ -16719,7 +16859,7 @@ func schema_k8sio_api_core_v1_EphemeralContainer(ref common.ReferenceCallback) c
},
},
SchemaProps: spec.SchemaProps{
- Description: "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
+ Description: "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
@@ -16783,11 +16923,30 @@ func schema_k8sio_api_core_v1_EphemeralContainer(ref common.ReferenceCallback) c
},
"restartPolicy": {
SchemaProps: spec.SchemaProps{
- Description: "Restart policy for the container to manage the restart behavior of each container within a pod. This may only be set for init containers. You cannot set this field on ephemeral containers.",
+ Description: "Restart policy for the container to manage the restart behavior of each container within a pod. You cannot set this field on ephemeral containers.",
Type: []string{"string"},
Format: "",
},
},
+ "restartPolicyRules": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "atomic",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Description: "Represents a list of rules to be checked to determine if the container should be restarted on exit. You cannot set this field on ephemeral containers.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/api/core/v1.ContainerRestartRule"),
+ },
+ },
+ },
+ },
+ },
"volumeMounts": {
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
@@ -16922,7 +17081,7 @@ func schema_k8sio_api_core_v1_EphemeralContainer(ref common.ReferenceCallback) c
},
},
Dependencies: []string{
- "k8s.io/api/core/v1.ContainerPort", "k8s.io/api/core/v1.ContainerResizePolicy", "k8s.io/api/core/v1.EnvFromSource", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.Lifecycle", "k8s.io/api/core/v1.Probe", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.SecurityContext", "k8s.io/api/core/v1.VolumeDevice", "k8s.io/api/core/v1.VolumeMount"},
+ "k8s.io/api/core/v1.ContainerPort", "k8s.io/api/core/v1.ContainerResizePolicy", "k8s.io/api/core/v1.ContainerRestartRule", "k8s.io/api/core/v1.EnvFromSource", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.Lifecycle", "k8s.io/api/core/v1.Probe", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.SecurityContext", "k8s.io/api/core/v1.VolumeDevice", "k8s.io/api/core/v1.VolumeMount"},
}
}
@@ -17027,7 +17186,7 @@ func schema_k8sio_api_core_v1_EphemeralContainerCommon(ref common.ReferenceCallb
},
},
SchemaProps: spec.SchemaProps{
- Description: "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
+ Description: "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
@@ -17091,11 +17250,30 @@ func schema_k8sio_api_core_v1_EphemeralContainerCommon(ref common.ReferenceCallb
},
"restartPolicy": {
SchemaProps: spec.SchemaProps{
- Description: "Restart policy for the container to manage the restart behavior of each container within a pod. This may only be set for init containers. You cannot set this field on ephemeral containers.",
+ Description: "Restart policy for the container to manage the restart behavior of each container within a pod. You cannot set this field on ephemeral containers.",
Type: []string{"string"},
Format: "",
},
},
+ "restartPolicyRules": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "atomic",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Description: "Represents a list of rules to be checked to determine if the container should be restarted on exit. You cannot set this field on ephemeral containers.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/api/core/v1.ContainerRestartRule"),
+ },
+ },
+ },
+ },
+ },
"volumeMounts": {
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
@@ -17223,7 +17401,7 @@ func schema_k8sio_api_core_v1_EphemeralContainerCommon(ref common.ReferenceCallb
},
},
Dependencies: []string{
- "k8s.io/api/core/v1.ContainerPort", "k8s.io/api/core/v1.ContainerResizePolicy", "k8s.io/api/core/v1.EnvFromSource", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.Lifecycle", "k8s.io/api/core/v1.Probe", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.SecurityContext", "k8s.io/api/core/v1.VolumeDevice", "k8s.io/api/core/v1.VolumeMount"},
+ "k8s.io/api/core/v1.ContainerPort", "k8s.io/api/core/v1.ContainerResizePolicy", "k8s.io/api/core/v1.ContainerRestartRule", "k8s.io/api/core/v1.EnvFromSource", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.Lifecycle", "k8s.io/api/core/v1.Probe", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.SecurityContext", "k8s.io/api/core/v1.VolumeDevice", "k8s.io/api/core/v1.VolumeMount"},
}
}
@@ -17593,6 +17771,57 @@ func schema_k8sio_api_core_v1_FCVolumeSource(ref common.ReferenceCallback) commo
}
}
+func schema_k8sio_api_core_v1_FileKeySelector(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "FileKeySelector selects a key of the env file.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "volumeName": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The name of the volume mount containing the env file.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "path": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The path within the volume from which to select the file. Must be relative and may not contain the '..' path or start with '..'.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "key": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The key within the env file. An invalid key will prevent the pod from starting. The keys defined within a source may consist of any printable ASCII characters except '='. During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "optional": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Specify whether the file or its key must be defined. If the file or key does not exist, then the env var is not published. If optional is set to true and the specified key does not exist, the environment variable will not be set in the Pod's containers.\n\nIf optional is set to false and the specified key does not exist, an error will be returned during Pod creation.",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"volumeName", "path", "key"},
+ },
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-map-type": "atomic",
+ },
+ },
+ },
+ }
+}
+
func schema_k8sio_api_core_v1_FlexPersistentVolumeSource(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -17902,7 +18131,7 @@ func schema_k8sio_api_core_v1_GlusterfsVolumeSource(ref common.ReferenceCallback
Properties: map[string]spec.Schema{
"endpoints": {
SchemaProps: spec.SchemaProps{
- Description: "endpoints is the endpoint name that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod",
+ Description: "endpoints is the endpoint name that details Glusterfs topology.",
Default: "",
Type: []string{"string"},
Format: "",
@@ -20612,7 +20841,7 @@ func schema_k8sio_api_core_v1_PersistentVolumeClaimSpec(ref common.ReferenceCall
},
"volumeAttributesClassName": {
SchemaProps: spec.SchemaProps{
- Description: "volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass will be applied to the claim but it's not allowed to reset this field to empty string once it is set. If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass will be set by the persistentvolume controller if it exists. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).",
+ Description: "volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, it can be changed after the claim is created. An empty string or nil value indicates that no VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/",
Type: []string{"string"},
Format: "",
},
@@ -20737,14 +20966,14 @@ func schema_k8sio_api_core_v1_PersistentVolumeClaimStatus(ref common.ReferenceCa
},
"currentVolumeAttributesClassName": {
SchemaProps: spec.SchemaProps{
- Description: "currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim This is a beta field and requires enabling VolumeAttributesClass feature (off by default).",
+ Description: "currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim",
Type: []string{"string"},
Format: "",
},
},
"modifyVolumeStatus": {
SchemaProps: spec.SchemaProps{
- Description: "ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. When this is unset, there is no ModifyVolume operation being attempted. This is a beta field and requires enabling VolumeAttributesClass feature (off by default).",
+ Description: "ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. When this is unset, there is no ModifyVolume operation being attempted.",
Ref: ref("k8s.io/api/core/v1.ModifyVolumeStatus"),
},
},
@@ -21249,7 +21478,7 @@ func schema_k8sio_api_core_v1_PersistentVolumeSpec(ref common.ReferenceCallback)
},
"volumeAttributesClassName": {
SchemaProps: spec.SchemaProps{
- Description: "Name of VolumeAttributesClass to which this persistent volume belongs. Empty value is not allowed. When this field is not set, it indicates that this volume does not belong to any VolumeAttributesClass. This field is mutable and can be changed by the CSI driver after a volume has been updated successfully to a new class. For an unbound PersistentVolume, the volumeAttributesClassName will be matched with unbound PersistentVolumeClaims during the binding process. This is a beta field and requires enabling VolumeAttributesClass feature (off by default).",
+ Description: "Name of VolumeAttributesClass to which this persistent volume belongs. Empty value is not allowed. When this field is not set, it indicates that this volume does not belong to any VolumeAttributesClass. This field is mutable and can be changed by the CSI driver after a volume has been updated successfully to a new class. For an unbound PersistentVolume, the volumeAttributesClassName will be matched with unbound PersistentVolumeClaims during the binding process.",
Type: []string{"string"},
Format: "",
},
@@ -21566,7 +21795,7 @@ func schema_k8sio_api_core_v1_PodAntiAffinity(ref common.ReferenceCallback) comm
},
},
SchemaProps: spec.SchemaProps{
- Description: "The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding \"weight\" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred.",
+ Description: "The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and subtracting \"weight\" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
@@ -21648,6 +21877,62 @@ func schema_k8sio_api_core_v1_PodAttachOptions(ref common.ReferenceCallback) com
}
}
+func schema_k8sio_api_core_v1_PodCertificateProjection(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "PodCertificateProjection provides a private key and X.509 certificate in the pod filesystem.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "signerName": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kubelet's generated CSRs will be addressed to this signer.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "keyType": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The type of keypair Kubelet will generate for the pod.\n\nValid values are \"RSA3072\", \"RSA4096\", \"ECDSAP256\", \"ECDSAP384\", \"ECDSAP521\", and \"ED25519\".",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "maxExpirationSeconds": {
+ SchemaProps: spec.SchemaProps{
+ Description: "maxExpirationSeconds is the maximum lifetime permitted for the certificate.\n\nKubelet copies this value verbatim into the PodCertificateRequests it generates for this projection.\n\nIf omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver will reject values shorter than 3600 (1 hour). The maximum allowable value is 7862400 (91 days).\n\nThe signer implementation is then free to issue a certificate with any lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 seconds (1 hour). This constraint is enforced by kube-apiserver. `kubernetes.io` signers will never issue certificates with a lifetime longer than 24 hours.",
+ Type: []string{"integer"},
+ Format: "int32",
+ },
+ },
+ "credentialBundlePath": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Write the credential bundle at this path in the projected volume.\n\nThe credential bundle is a single file that contains multiple PEM blocks. The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private key.\n\nThe remaining blocks are CERTIFICATE blocks, containing the issued certificate chain from the signer (leaf and any intermediates).\n\nUsing credentialBundlePath lets your Pod's application code make a single atomic read that retrieves a consistent key and certificate chain. If you project them to separate files, your application code will need to additionally check that the leaf certificate was issued to the key.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "keyPath": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Write the key at this path in the projected volume.\n\nMost applications should use credentialBundlePath. When using keyPath and certificateChainPath, your application needs to check that the key and leaf certificate are consistent, because it is possible to read the files mid-rotation.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "certificateChainPath": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Write the certificate chain at this path in the projected volume.\n\nMost applications should use credentialBundlePath. When using keyPath and certificateChainPath, your application needs to check that the key and leaf certificate are consistent, because it is possible to read the files mid-rotation.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"signerName", "keyType"},
+ },
+ },
+ }
+}
+
func schema_k8sio_api_core_v1_PodCondition(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -21897,6 +22182,49 @@ func schema_k8sio_api_core_v1_PodExecOptions(ref common.ReferenceCallback) commo
}
}
+func schema_k8sio_api_core_v1_PodExtendedResourceClaimStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "PodExtendedResourceClaimStatus is stored in the PodStatus for the extended resource requests backed by DRA. It stores the generated name for the corresponding special ResourceClaim created by the scheduler.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "requestMappings": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "atomic",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Description: "RequestMappings identifies the mapping of to device request in the generated ResourceClaim.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/api/core/v1.ContainerExtendedResourceRequest"),
+ },
+ },
+ },
+ },
+ },
+ "resourceClaimName": {
+ SchemaProps: spec.SchemaProps{
+ Description: "ResourceClaimName is the name of the ResourceClaim that was generated for the Pod in the namespace of the Pod.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"requestMappings", "resourceClaimName"},
+ },
+ },
+ Dependencies: []string{
+ "k8s.io/api/core/v1.ContainerExtendedResourceRequest"},
+ }
+}
+
func schema_k8sio_api_core_v1_PodIP(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -22614,7 +22942,7 @@ func schema_k8sio_api_core_v1_PodSpec(ref common.ReferenceCallback) common.OpenA
},
"hostNetwork": {
SchemaProps: spec.SchemaProps{
- Description: "Host networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false.",
+ Description: "Host networking requested for this pod. Use the host's network namespace. When using HostNetwork you should specify ports so the scheduler is aware. When `hostNetwork` is true, specified `hostPort` fields in port definitions must match `containerPort`, and unspecified `hostPort` fields in port definitions are defaulted to match `containerPort`. Default to false.",
Type: []string{"boolean"},
Format: "",
},
@@ -22849,7 +23177,7 @@ func schema_k8sio_api_core_v1_PodSpec(ref common.ReferenceCallback) common.OpenA
},
"os": {
SchemaProps: spec.SchemaProps{
- Description: "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.hostUsers - spec.securityContext.appArmorProfile - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.securityContext.supplementalGroupsPolicy - spec.containers[*].securityContext.appArmorProfile - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup",
+ Description: "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.hostUsers - spec.resources - spec.securityContext.appArmorProfile - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.securityContext.supplementalGroupsPolicy - spec.containers[*].securityContext.appArmorProfile - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup",
Ref: ref("k8s.io/api/core/v1.PodOS"),
},
},
@@ -22910,10 +23238,17 @@ func schema_k8sio_api_core_v1_PodSpec(ref common.ReferenceCallback) common.OpenA
},
"resources": {
SchemaProps: spec.SchemaProps{
- Description: "Resources is the total amount of CPU and Memory resources required by all containers in the pod. It supports specifying Requests and Limits for \"cpu\" and \"memory\" resource names only. ResourceClaims are not supported.\n\nThis field enables fine-grained control over resource allocation for the entire pod, allowing resource sharing among containers in a pod.\n\nThis is an alpha field and requires enabling the PodLevelResources feature gate.",
+ Description: "Resources is the total amount of CPU and Memory resources required by all containers in the pod. It supports specifying Requests and Limits for \"cpu\", \"memory\" and \"hugepages-\" resource names only. ResourceClaims are not supported.\n\nThis field enables fine-grained control over resource allocation for the entire pod, allowing resource sharing among containers in a pod.\n\nThis is an alpha field and requires enabling the PodLevelResources feature gate.",
Ref: ref("k8s.io/api/core/v1.ResourceRequirements"),
},
},
+ "hostnameOverride": {
+ SchemaProps: spec.SchemaProps{
+ Description: "HostnameOverride specifies an explicit override for the pod's hostname as perceived by the pod. This field only specifies the pod's hostname and does not affect its DNS records. When this field is set to a non-empty string: - It takes precedence over the values set in `hostname` and `subdomain`. - The Pod's hostname will be set to this value. - `setHostnameAsFQDN` must be nil or set to false. - `hostNetwork` must be set to false.\n\nThis field must be a valid DNS subdomain as defined in RFC 1123 and contain at most 64 characters. Requires the HostnameOverride feature gate to be enabled.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
},
Required: []string{"containers"},
},
@@ -23151,11 +23486,17 @@ func schema_k8sio_api_core_v1_PodStatus(ref common.ReferenceCallback) common.Ope
},
},
},
+ "extendedResourceClaimStatus": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Status of extended resource claim backed by DRA.",
+ Ref: ref("k8s.io/api/core/v1.PodExtendedResourceClaimStatus"),
+ },
+ },
},
},
},
Dependencies: []string{
- "k8s.io/api/core/v1.ContainerStatus", "k8s.io/api/core/v1.HostIP", "k8s.io/api/core/v1.PodCondition", "k8s.io/api/core/v1.PodIP", "k8s.io/api/core/v1.PodResourceClaimStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
+ "k8s.io/api/core/v1.ContainerStatus", "k8s.io/api/core/v1.HostIP", "k8s.io/api/core/v1.PodCondition", "k8s.io/api/core/v1.PodExtendedResourceClaimStatus", "k8s.io/api/core/v1.PodIP", "k8s.io/api/core/v1.PodResourceClaimStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
}
}
@@ -24552,7 +24893,7 @@ func schema_k8sio_api_core_v1_ResourceRequirements(ref common.ReferenceCallback)
},
},
SchemaProps: spec.SchemaProps{
- Description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable. It can only be set for containers.",
+ Description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis field depends on the DynamicResourceAllocation feature gate.\n\nThis field is immutable. It can only be set for containers.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
@@ -26330,7 +26671,7 @@ func schema_k8sio_api_core_v1_Taint(ref common.ReferenceCallback) common.OpenAPI
},
"timeAdded": {
SchemaProps: spec.SchemaProps{
- Description: "TimeAdded represents the time at which the taint was added. It is only written for NoExecute taints.",
+ Description: "TimeAdded represents the time at which the taint was added.",
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
},
},
@@ -26709,13 +27050,13 @@ func schema_k8sio_api_core_v1_Volume(ref common.ReferenceCallback) common.OpenAP
},
"iscsi": {
SchemaProps: spec.SchemaProps{
- Description: "iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md",
+ Description: "iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi",
Ref: ref("k8s.io/api/core/v1.ISCSIVolumeSource"),
},
},
"glusterfs": {
SchemaProps: spec.SchemaProps{
- Description: "glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. More info: https://examples.k8s.io/volumes/glusterfs/README.md",
+ Description: "glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.",
Ref: ref("k8s.io/api/core/v1.GlusterfsVolumeSource"),
},
},
@@ -26727,7 +27068,7 @@ func schema_k8sio_api_core_v1_Volume(ref common.ReferenceCallback) common.OpenAP
},
"rbd": {
SchemaProps: spec.SchemaProps{
- Description: "rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. More info: https://examples.k8s.io/volumes/rbd/README.md",
+ Description: "rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.",
Ref: ref("k8s.io/api/core/v1.RBDVolumeSource"),
},
},
@@ -27052,11 +27393,17 @@ func schema_k8sio_api_core_v1_VolumeProjection(ref common.ReferenceCallback) com
Ref: ref("k8s.io/api/core/v1.ClusterTrustBundleProjection"),
},
},
+ "podCertificate": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Projects an auto-rotating credential bundle (private key and certificate chain) that the pod can use either as a TLS client or server.\n\nKubelet generates a private key and uses it to send a PodCertificateRequest to the named signer. Once the signer approves the request and issues a certificate chain, Kubelet writes the key and certificate chain to the pod filesystem. The pod does not start until certificates have been issued for each podCertificate projected volume source in its spec.\n\nKubelet will begin trying to rotate the certificate at the time indicated by the signer using the PodCertificateRequest.Status.BeginRefreshAt timestamp.\n\nKubelet can write a single file, indicated by the credentialBundlePath field, or separate files, indicated by the keyPath and certificateChainPath fields.\n\nThe credential bundle is a single file in PEM format. The first PEM entry is the private key (in PKCS#8 format), and the remaining PEM entries are the certificate chain issued by the signer (typically, signers will return their certificate chain in leaf-to-root order).\n\nPrefer using the credential bundle format, since your application code can read it atomically. If you use keyPath and certificateChainPath, your application must make two separate file reads. If these coincide with a certificate rotation, it is possible that the private key and leaf certificate you read may not correspond to each other. Your application will need to check for this condition, and re-read until they are consistent.\n\nThe named signer controls chooses the format of the certificate it issues; consult the signer implementation's documentation to learn how to use the certificates it issues.",
+ Ref: ref("k8s.io/api/core/v1.PodCertificateProjection"),
+ },
+ },
},
},
},
Dependencies: []string{
- "k8s.io/api/core/v1.ClusterTrustBundleProjection", "k8s.io/api/core/v1.ConfigMapProjection", "k8s.io/api/core/v1.DownwardAPIProjection", "k8s.io/api/core/v1.SecretProjection", "k8s.io/api/core/v1.ServiceAccountTokenProjection"},
+ "k8s.io/api/core/v1.ClusterTrustBundleProjection", "k8s.io/api/core/v1.ConfigMapProjection", "k8s.io/api/core/v1.DownwardAPIProjection", "k8s.io/api/core/v1.PodCertificateProjection", "k8s.io/api/core/v1.SecretProjection", "k8s.io/api/core/v1.ServiceAccountTokenProjection"},
}
}
@@ -27154,13 +27501,13 @@ func schema_k8sio_api_core_v1_VolumeSource(ref common.ReferenceCallback) common.
},
"iscsi": {
SchemaProps: spec.SchemaProps{
- Description: "iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md",
+ Description: "iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi",
Ref: ref("k8s.io/api/core/v1.ISCSIVolumeSource"),
},
},
"glusterfs": {
SchemaProps: spec.SchemaProps{
- Description: "glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. More info: https://examples.k8s.io/volumes/glusterfs/README.md",
+ Description: "glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.",
Ref: ref("k8s.io/api/core/v1.GlusterfsVolumeSource"),
},
},
@@ -27172,7 +27519,7 @@ func schema_k8sio_api_core_v1_VolumeSource(ref common.ReferenceCallback) common.
},
"rbd": {
SchemaProps: spec.SchemaProps{
- Description: "rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. More info: https://examples.k8s.io/volumes/rbd/README.md",
+ Description: "rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.",
Ref: ref("k8s.io/api/core/v1.RBDVolumeSource"),
},
},
@@ -28549,7 +28896,7 @@ func schema_k8sio_api_networking_v1_NetworkPolicySpec(ref common.ReferenceCallba
Properties: map[string]spec.Schema{
"podSelector": {
SchemaProps: spec.SchemaProps{
- Description: "podSelector selects the pods to which this NetworkPolicy object applies. The array of ingress rules is applied to any pods selected by this field. Multiple network policies can select the same set of pods. In this case, the ingress rules for each are combined additively. This field is NOT optional and follows standard label selector semantics. An empty podSelector matches all pods in this namespace.",
+ Description: "podSelector selects the pods to which this NetworkPolicy object applies. The array of rules is applied to any pods selected by this field. An empty selector matches all pods in the policy's namespace. Multiple network policies can select the same set of pods. In this case, the ingress rules for each are combined additively. This field is optional. If it is not specified, it defaults to an empty selector.",
Default: map[string]interface{}{},
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"),
},
@@ -28614,7 +28961,6 @@ func schema_k8sio_api_networking_v1_NetworkPolicySpec(ref common.ReferenceCallba
},
},
},
- Required: []string{"podSelector"},
},
},
Dependencies: []string{
diff --git a/pkg/client/kubernetes/applier_test.go b/pkg/client/kubernetes/applier_test.go
index 158065c2ac0..99ee2863204 100644
--- a/pkg/client/kubernetes/applier_test.go
+++ b/pkg/client/kubernetes/applier_test.go
@@ -204,6 +204,7 @@ spec:
newService.Spec.ClusterIP = ""
newService.Annotations = map[string]string{}
expected = oldService.DeepCopy()
+ expected.TypeMeta = metav1.TypeMeta{}
expected.ResourceVersion = "2"
})
@@ -627,6 +628,7 @@ spec:
newDeployment = oldDeployment.DeepCopy()
expected = oldDeployment.DeepCopy()
+ expected.TypeMeta = metav1.TypeMeta{}
expected.ResourceVersion = "2"
})
diff --git a/pkg/client/kubernetes/chartapplier_test.go b/pkg/client/kubernetes/chartapplier_test.go
index bbcf5691c33..7cbcd4dc8dd 100644
--- a/pkg/client/kubernetes/chartapplier_test.go
+++ b/pkg/client/kubernetes/chartapplier_test.go
@@ -69,7 +69,6 @@ var _ = Describe("chart applier", func() {
mapper.Add(corev1.SchemeGroupVersion.WithKind("ConfigMap"), meta.RESTScopeNamespace)
expectedCM = &corev1.ConfigMap{
- TypeMeta: configMapTypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: configMapName,
Namespace: namespace,
@@ -105,7 +104,6 @@ var _ = Describe("chart applier", func() {
const newNS = "other-namespace"
existingCM := &corev1.ConfigMap{
- TypeMeta: configMapTypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: configMapName,
Namespace: newNS,
@@ -164,7 +162,6 @@ var _ = Describe("chart applier", func() {
test := func(chartPath string) {
It("deletes the chart with default values", func() {
existingCM := &corev1.ConfigMap{
- TypeMeta: configMapTypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: configMapName,
Namespace: namespace,
@@ -181,7 +178,6 @@ var _ = Describe("chart applier", func() {
const newNS = "other-namespace"
existingCM := &corev1.ConfigMap{
- TypeMeta: configMapTypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: configMapName,
Namespace: newNS,
@@ -267,7 +263,6 @@ var _ = Describe("chart applier", func() {
const newNS = "other-namespace"
existingCM := &corev1.ConfigMap{
- TypeMeta: configMapTypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: configMapName,
Namespace: newNS,
@@ -325,7 +320,6 @@ var _ = Describe("chart applier", func() {
test := func(archive []byte) {
It("deletes the chart with default values", func() {
existingCM := &corev1.ConfigMap{
- TypeMeta: configMapTypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: configMapName,
Namespace: namespace,
@@ -342,7 +336,6 @@ var _ = Describe("chart applier", func() {
const newNS = "other-namespace"
existingCM := &corev1.ConfigMap{
- TypeMeta: configMapTypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: configMapName,
Namespace: newNS,
diff --git a/pkg/client/seedmanagement/applyconfiguration/internal/internal.go b/pkg/client/seedmanagement/applyconfiguration/internal/internal.go
deleted file mode 100644
index 6b06d7c5835..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/internal/internal.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package internal
-
-import (
- "fmt"
- "sync"
-
- typed "sigs.k8s.io/structured-merge-diff/v4/typed"
-)
-
-func Parser() *typed.Parser {
- parserOnce.Do(func() {
- var err error
- parser, err = typed.NewParser(schemaYAML)
- if err != nil {
- panic(fmt.Sprintf("Failed to parse schema: %v", err))
- }
- })
- return parser
-}
-
-var parserOnce sync.Once
-var parser *typed.Parser
-var schemaYAML = typed.YAMLObject(`types:
-- name: __untyped_atomic_
- scalar: untyped
- list:
- elementType:
- namedType: __untyped_atomic_
- elementRelationship: atomic
- map:
- elementType:
- namedType: __untyped_atomic_
- elementRelationship: atomic
-- name: __untyped_deduced_
- scalar: untyped
- list:
- elementType:
- namedType: __untyped_atomic_
- elementRelationship: atomic
- map:
- elementType:
- namedType: __untyped_deduced_
- elementRelationship: separable
-`)
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/gardenlet.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/gardenlet.go
deleted file mode 100644
index 47c1e2261e5..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/gardenlet.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1"
- runtime "k8s.io/apimachinery/pkg/runtime"
-)
-
-// GardenletApplyConfiguration represents an declarative configuration of the Gardenlet type for use
-// with apply.
-type GardenletApplyConfiguration struct {
- Deployment *GardenletDeploymentApplyConfiguration `json:"deployment,omitempty"`
- Config *runtime.RawExtension `json:"config,omitempty"`
- Bootstrap *seedmanagementv1alpha1.Bootstrap `json:"bootstrap,omitempty"`
- MergeWithParent *bool `json:"mergeWithParent,omitempty"`
-}
-
-// GardenletApplyConfiguration constructs an declarative configuration of the Gardenlet type for use with
-// apply.
-func Gardenlet() *GardenletApplyConfiguration {
- return &GardenletApplyConfiguration{}
-}
-
-// WithDeployment sets the Deployment field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Deployment field is set to the value of the last call.
-func (b *GardenletApplyConfiguration) WithDeployment(value *GardenletDeploymentApplyConfiguration) *GardenletApplyConfiguration {
- b.Deployment = value
- return b
-}
-
-// WithConfig sets the Config field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Config field is set to the value of the last call.
-func (b *GardenletApplyConfiguration) WithConfig(value runtime.RawExtension) *GardenletApplyConfiguration {
- b.Config = &value
- return b
-}
-
-// WithBootstrap sets the Bootstrap field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Bootstrap field is set to the value of the last call.
-func (b *GardenletApplyConfiguration) WithBootstrap(value seedmanagementv1alpha1.Bootstrap) *GardenletApplyConfiguration {
- b.Bootstrap = &value
- return b
-}
-
-// WithMergeWithParent sets the MergeWithParent field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the MergeWithParent field is set to the value of the last call.
-func (b *GardenletApplyConfiguration) WithMergeWithParent(value bool) *GardenletApplyConfiguration {
- b.MergeWithParent = &value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/gardenletdeployment.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/gardenletdeployment.go
deleted file mode 100644
index a7fe56c0e22..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/gardenletdeployment.go
+++ /dev/null
@@ -1,137 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- "maps"
-
- v1 "k8s.io/api/core/v1"
-)
-
-// GardenletDeploymentApplyConfiguration represents an declarative configuration of the GardenletDeployment type for use
-// with apply.
-type GardenletDeploymentApplyConfiguration struct {
- ReplicaCount *int32 `json:"replicaCount,omitempty"`
- RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"`
- ServiceAccountName *string `json:"serviceAccountName,omitempty"`
- Image *ImageApplyConfiguration `json:"image,omitempty"`
- Resources *v1.ResourceRequirements `json:"resources,omitempty"`
- PodLabels map[string]string `json:"podLabels,omitempty"`
- PodAnnotations map[string]string `json:"podAnnotations,omitempty"`
- AdditionalVolumes []v1.Volume `json:"additionalVolumes,omitempty"`
- AdditionalVolumeMounts []v1.VolumeMount `json:"additionalVolumeMounts,omitempty"`
- Env []v1.EnvVar `json:"env,omitempty"`
- VPA *bool `json:"vpa,omitempty"`
-}
-
-// GardenletDeploymentApplyConfiguration constructs an declarative configuration of the GardenletDeployment type for use with
-// apply.
-func GardenletDeployment() *GardenletDeploymentApplyConfiguration {
- return &GardenletDeploymentApplyConfiguration{}
-}
-
-// WithReplicaCount sets the ReplicaCount field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ReplicaCount field is set to the value of the last call.
-func (b *GardenletDeploymentApplyConfiguration) WithReplicaCount(value int32) *GardenletDeploymentApplyConfiguration {
- b.ReplicaCount = &value
- return b
-}
-
-// WithRevisionHistoryLimit sets the RevisionHistoryLimit field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the RevisionHistoryLimit field is set to the value of the last call.
-func (b *GardenletDeploymentApplyConfiguration) WithRevisionHistoryLimit(value int32) *GardenletDeploymentApplyConfiguration {
- b.RevisionHistoryLimit = &value
- return b
-}
-
-// WithServiceAccountName sets the ServiceAccountName field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ServiceAccountName field is set to the value of the last call.
-func (b *GardenletDeploymentApplyConfiguration) WithServiceAccountName(value string) *GardenletDeploymentApplyConfiguration {
- b.ServiceAccountName = &value
- return b
-}
-
-// WithImage sets the Image field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Image field is set to the value of the last call.
-func (b *GardenletDeploymentApplyConfiguration) WithImage(value *ImageApplyConfiguration) *GardenletDeploymentApplyConfiguration {
- b.Image = value
- return b
-}
-
-// WithResources sets the Resources field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Resources field is set to the value of the last call.
-func (b *GardenletDeploymentApplyConfiguration) WithResources(value v1.ResourceRequirements) *GardenletDeploymentApplyConfiguration {
- b.Resources = &value
- return b
-}
-
-// WithPodLabels puts the entries into the PodLabels field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the PodLabels field,
-// overwriting an existing map entries in PodLabels field with the same key.
-func (b *GardenletDeploymentApplyConfiguration) WithPodLabels(entries map[string]string) *GardenletDeploymentApplyConfiguration {
- if b.PodLabels == nil && len(entries) > 0 {
- b.PodLabels = make(map[string]string, len(entries))
- }
- maps.Copy(b.PodLabels, entries)
- return b
-}
-
-// WithPodAnnotations puts the entries into the PodAnnotations field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the PodAnnotations field,
-// overwriting an existing map entries in PodAnnotations field with the same key.
-func (b *GardenletDeploymentApplyConfiguration) WithPodAnnotations(entries map[string]string) *GardenletDeploymentApplyConfiguration {
- if b.PodAnnotations == nil && len(entries) > 0 {
- b.PodAnnotations = make(map[string]string, len(entries))
- }
- maps.Copy(b.PodAnnotations, entries)
- return b
-}
-
-// WithAdditionalVolumes adds the given value to the AdditionalVolumes field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the AdditionalVolumes field.
-func (b *GardenletDeploymentApplyConfiguration) WithAdditionalVolumes(values ...v1.Volume) *GardenletDeploymentApplyConfiguration {
- for i := range values {
- b.AdditionalVolumes = append(b.AdditionalVolumes, values[i])
- }
- return b
-}
-
-// WithAdditionalVolumeMounts adds the given value to the AdditionalVolumeMounts field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the AdditionalVolumeMounts field.
-func (b *GardenletDeploymentApplyConfiguration) WithAdditionalVolumeMounts(values ...v1.VolumeMount) *GardenletDeploymentApplyConfiguration {
- for i := range values {
- b.AdditionalVolumeMounts = append(b.AdditionalVolumeMounts, values[i])
- }
- return b
-}
-
-// WithEnv adds the given value to the Env field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the Env field.
-func (b *GardenletDeploymentApplyConfiguration) WithEnv(values ...v1.EnvVar) *GardenletDeploymentApplyConfiguration {
- for i := range values {
- b.Env = append(b.Env, values[i])
- }
- return b
-}
-
-// WithVPA sets the VPA field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the VPA field is set to the value of the last call.
-func (b *GardenletDeploymentApplyConfiguration) WithVPA(value bool) *GardenletDeploymentApplyConfiguration {
- b.VPA = &value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/image.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/image.go
deleted file mode 100644
index 8117ca1106b..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/image.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- v1 "k8s.io/api/core/v1"
-)
-
-// ImageApplyConfiguration represents an declarative configuration of the Image type for use
-// with apply.
-type ImageApplyConfiguration struct {
- Repository *string `json:"repository,omitempty"`
- Tag *string `json:"tag,omitempty"`
- PullPolicy *v1.PullPolicy `json:"pullPolicy,omitempty"`
-}
-
-// ImageApplyConfiguration constructs an declarative configuration of the Image type for use with
-// apply.
-func Image() *ImageApplyConfiguration {
- return &ImageApplyConfiguration{}
-}
-
-// WithRepository sets the Repository field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Repository field is set to the value of the last call.
-func (b *ImageApplyConfiguration) WithRepository(value string) *ImageApplyConfiguration {
- b.Repository = &value
- return b
-}
-
-// WithTag sets the Tag field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Tag field is set to the value of the last call.
-func (b *ImageApplyConfiguration) WithTag(value string) *ImageApplyConfiguration {
- b.Tag = &value
- return b
-}
-
-// WithPullPolicy sets the PullPolicy field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the PullPolicy field is set to the value of the last call.
-func (b *ImageApplyConfiguration) WithPullPolicy(value v1.PullPolicy) *ImageApplyConfiguration {
- b.PullPolicy = &value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseed.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseed.go
deleted file mode 100644
index e5716ff3e8f..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseed.go
+++ /dev/null
@@ -1,206 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- "maps"
-
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- types "k8s.io/apimachinery/pkg/types"
- v1 "k8s.io/client-go/applyconfigurations/meta/v1"
-)
-
-// ManagedSeedApplyConfiguration represents an declarative configuration of the ManagedSeed type for use
-// with apply.
-type ManagedSeedApplyConfiguration struct {
- v1.TypeMetaApplyConfiguration `json:",inline"`
- *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
- Spec *ManagedSeedSpecApplyConfiguration `json:"spec,omitempty"`
- Status *ManagedSeedStatusApplyConfiguration `json:"status,omitempty"`
-}
-
-// ManagedSeed constructs an declarative configuration of the ManagedSeed type for use with
-// apply.
-func ManagedSeed(name, namespace string) *ManagedSeedApplyConfiguration {
- b := &ManagedSeedApplyConfiguration{}
- b.WithName(name)
- b.WithNamespace(namespace)
- b.WithKind("ManagedSeed")
- b.WithAPIVersion("seedmanagement.gardener.cloud/v1alpha1")
- return b
-}
-
-// WithKind sets the Kind field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Kind field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithKind(value string) *ManagedSeedApplyConfiguration {
- b.Kind = &value
- return b
-}
-
-// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the APIVersion field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithAPIVersion(value string) *ManagedSeedApplyConfiguration {
- b.APIVersion = &value
- return b
-}
-
-// WithName sets the Name field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Name field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithName(value string) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Name = &value
- return b
-}
-
-// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the GenerateName field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithGenerateName(value string) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.GenerateName = &value
- return b
-}
-
-// WithNamespace sets the Namespace field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Namespace field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithNamespace(value string) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Namespace = &value
- return b
-}
-
-// WithUID sets the UID field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UID field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithUID(value types.UID) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.UID = &value
- return b
-}
-
-// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ResourceVersion field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithResourceVersion(value string) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.ResourceVersion = &value
- return b
-}
-
-// WithGeneration sets the Generation field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Generation field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithGeneration(value int64) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Generation = &value
- return b
-}
-
-// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the CreationTimestamp field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.CreationTimestamp = &value
- return b
-}
-
-// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionTimestamp = &value
- return b
-}
-
-// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionGracePeriodSeconds = &value
- return b
-}
-
-// WithLabels puts the entries into the Labels field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Labels field,
-// overwriting an existing map entries in Labels field with the same key.
-func (b *ManagedSeedApplyConfiguration) WithLabels(entries map[string]string) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Labels == nil && len(entries) > 0 {
- b.Labels = make(map[string]string, len(entries))
- }
-
- maps.Copy(b.Labels, entries)
- return b
-}
-
-// WithAnnotations puts the entries into the Annotations field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Annotations field,
-// overwriting an existing map entries in Annotations field with the same key.
-func (b *ManagedSeedApplyConfiguration) WithAnnotations(entries map[string]string) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Annotations == nil && len(entries) > 0 {
- b.Annotations = make(map[string]string, len(entries))
- }
- maps.Copy(b.Annotations, entries)
- return b
-}
-
-// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
-func (b *ManagedSeedApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- if values[i] == nil {
- panic("nil value passed to WithOwnerReferences")
- }
- b.OwnerReferences = append(b.OwnerReferences, *values[i])
- }
- return b
-}
-
-// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the Finalizers field.
-func (b *ManagedSeedApplyConfiguration) WithFinalizers(values ...string) *ManagedSeedApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- b.Finalizers = append(b.Finalizers, values[i])
- }
- return b
-}
-
-func (b *ManagedSeedApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
- if b.ObjectMetaApplyConfiguration == nil {
- b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
- }
-}
-
-// WithSpec sets the Spec field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Spec field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithSpec(value *ManagedSeedSpecApplyConfiguration) *ManagedSeedApplyConfiguration {
- b.Spec = value
- return b
-}
-
-// WithStatus sets the Status field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Status field is set to the value of the last call.
-func (b *ManagedSeedApplyConfiguration) WithStatus(value *ManagedSeedStatusApplyConfiguration) *ManagedSeedApplyConfiguration {
- b.Status = value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedset.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedset.go
deleted file mode 100644
index 2525ac6e89d..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedset.go
+++ /dev/null
@@ -1,205 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- "maps"
-
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- types "k8s.io/apimachinery/pkg/types"
- v1 "k8s.io/client-go/applyconfigurations/meta/v1"
-)
-
-// ManagedSeedSetApplyConfiguration represents an declarative configuration of the ManagedSeedSet type for use
-// with apply.
-type ManagedSeedSetApplyConfiguration struct {
- v1.TypeMetaApplyConfiguration `json:",inline"`
- *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
- Spec *ManagedSeedSetSpecApplyConfiguration `json:"spec,omitempty"`
- Status *ManagedSeedSetStatusApplyConfiguration `json:"status,omitempty"`
-}
-
-// ManagedSeedSet constructs an declarative configuration of the ManagedSeedSet type for use with
-// apply.
-func ManagedSeedSet(name, namespace string) *ManagedSeedSetApplyConfiguration {
- b := &ManagedSeedSetApplyConfiguration{}
- b.WithName(name)
- b.WithNamespace(namespace)
- b.WithKind("ManagedSeedSet")
- b.WithAPIVersion("seedmanagement.gardener.cloud/v1alpha1")
- return b
-}
-
-// WithKind sets the Kind field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Kind field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithKind(value string) *ManagedSeedSetApplyConfiguration {
- b.Kind = &value
- return b
-}
-
-// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the APIVersion field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithAPIVersion(value string) *ManagedSeedSetApplyConfiguration {
- b.APIVersion = &value
- return b
-}
-
-// WithName sets the Name field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Name field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithName(value string) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Name = &value
- return b
-}
-
-// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the GenerateName field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithGenerateName(value string) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.GenerateName = &value
- return b
-}
-
-// WithNamespace sets the Namespace field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Namespace field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithNamespace(value string) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Namespace = &value
- return b
-}
-
-// WithUID sets the UID field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UID field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithUID(value types.UID) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.UID = &value
- return b
-}
-
-// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ResourceVersion field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithResourceVersion(value string) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.ResourceVersion = &value
- return b
-}
-
-// WithGeneration sets the Generation field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Generation field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithGeneration(value int64) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Generation = &value
- return b
-}
-
-// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the CreationTimestamp field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.CreationTimestamp = &value
- return b
-}
-
-// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionTimestamp = &value
- return b
-}
-
-// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionGracePeriodSeconds = &value
- return b
-}
-
-// WithLabels puts the entries into the Labels field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Labels field,
-// overwriting an existing map entries in Labels field with the same key.
-func (b *ManagedSeedSetApplyConfiguration) WithLabels(entries map[string]string) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Labels == nil && len(entries) > 0 {
- b.Labels = make(map[string]string, len(entries))
- }
- maps.Copy(b.Labels, entries)
- return b
-}
-
-// WithAnnotations puts the entries into the Annotations field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Annotations field,
-// overwriting an existing map entries in Annotations field with the same key.
-func (b *ManagedSeedSetApplyConfiguration) WithAnnotations(entries map[string]string) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Annotations == nil && len(entries) > 0 {
- b.Annotations = make(map[string]string, len(entries))
- }
- maps.Copy(b.Annotations, entries)
- return b
-}
-
-// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
-func (b *ManagedSeedSetApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- if values[i] == nil {
- panic("nil value passed to WithOwnerReferences")
- }
- b.OwnerReferences = append(b.OwnerReferences, *values[i])
- }
- return b
-}
-
-// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the Finalizers field.
-func (b *ManagedSeedSetApplyConfiguration) WithFinalizers(values ...string) *ManagedSeedSetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- b.Finalizers = append(b.Finalizers, values[i])
- }
- return b
-}
-
-func (b *ManagedSeedSetApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
- if b.ObjectMetaApplyConfiguration == nil {
- b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
- }
-}
-
-// WithSpec sets the Spec field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Spec field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithSpec(value *ManagedSeedSetSpecApplyConfiguration) *ManagedSeedSetApplyConfiguration {
- b.Spec = value
- return b
-}
-
-// WithStatus sets the Status field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Status field is set to the value of the last call.
-func (b *ManagedSeedSetApplyConfiguration) WithStatus(value *ManagedSeedSetStatusApplyConfiguration) *ManagedSeedSetApplyConfiguration {
- b.Status = value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedsetspec.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedsetspec.go
deleted file mode 100644
index 57b21d0efcb..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedsetspec.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- v1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
- v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-)
-
-// ManagedSeedSetSpecApplyConfiguration represents an declarative configuration of the ManagedSeedSetSpec type for use
-// with apply.
-type ManagedSeedSetSpecApplyConfiguration struct {
- Replicas *int32 `json:"replicas,omitempty"`
- Selector *v1.LabelSelector `json:"selector,omitempty"`
- Template *ManagedSeedTemplateApplyConfiguration `json:"template,omitempty"`
- ShootTemplate *v1beta1.ShootTemplate `json:"shootTemplate,omitempty"`
- UpdateStrategy *UpdateStrategyApplyConfiguration `json:"updateStrategy,omitempty"`
- RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"`
-}
-
-// ManagedSeedSetSpecApplyConfiguration constructs an declarative configuration of the ManagedSeedSetSpec type for use with
-// apply.
-func ManagedSeedSetSpec() *ManagedSeedSetSpecApplyConfiguration {
- return &ManagedSeedSetSpecApplyConfiguration{}
-}
-
-// WithReplicas sets the Replicas field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Replicas field is set to the value of the last call.
-func (b *ManagedSeedSetSpecApplyConfiguration) WithReplicas(value int32) *ManagedSeedSetSpecApplyConfiguration {
- b.Replicas = &value
- return b
-}
-
-// WithSelector sets the Selector field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Selector field is set to the value of the last call.
-func (b *ManagedSeedSetSpecApplyConfiguration) WithSelector(value v1.LabelSelector) *ManagedSeedSetSpecApplyConfiguration {
- b.Selector = &value
- return b
-}
-
-// WithTemplate sets the Template field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Template field is set to the value of the last call.
-func (b *ManagedSeedSetSpecApplyConfiguration) WithTemplate(value *ManagedSeedTemplateApplyConfiguration) *ManagedSeedSetSpecApplyConfiguration {
- b.Template = value
- return b
-}
-
-// WithShootTemplate sets the ShootTemplate field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ShootTemplate field is set to the value of the last call.
-func (b *ManagedSeedSetSpecApplyConfiguration) WithShootTemplate(value v1beta1.ShootTemplate) *ManagedSeedSetSpecApplyConfiguration {
- b.ShootTemplate = &value
- return b
-}
-
-// WithUpdateStrategy sets the UpdateStrategy field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UpdateStrategy field is set to the value of the last call.
-func (b *ManagedSeedSetSpecApplyConfiguration) WithUpdateStrategy(value *UpdateStrategyApplyConfiguration) *ManagedSeedSetSpecApplyConfiguration {
- b.UpdateStrategy = value
- return b
-}
-
-// WithRevisionHistoryLimit sets the RevisionHistoryLimit field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the RevisionHistoryLimit field is set to the value of the last call.
-func (b *ManagedSeedSetSpecApplyConfiguration) WithRevisionHistoryLimit(value int32) *ManagedSeedSetSpecApplyConfiguration {
- b.RevisionHistoryLimit = &value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedsetstatus.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedsetstatus.go
deleted file mode 100644
index d57e1731125..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedsetstatus.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- v1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
-)
-
-// ManagedSeedSetStatusApplyConfiguration represents an declarative configuration of the ManagedSeedSetStatus type for use
-// with apply.
-type ManagedSeedSetStatusApplyConfiguration struct {
- ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
- Replicas *int32 `json:"replicas,omitempty"`
- ReadyReplicas *int32 `json:"readyReplicas,omitempty"`
- NextReplicaNumber *int32 `json:"nextReplicaNumber,omitempty"`
- CurrentReplicas *int32 `json:"currentReplicas,omitempty"`
- UpdatedReplicas *int32 `json:"updatedReplicas,omitempty"`
- CurrentRevision *string `json:"currentRevision,omitempty"`
- UpdateRevision *string `json:"updateRevision,omitempty"`
- CollisionCount *int32 `json:"collisionCount,omitempty"`
- Conditions []v1beta1.Condition `json:"conditions,omitempty"`
- PendingReplica *PendingReplicaApplyConfiguration `json:"pendingReplica,omitempty"`
-}
-
-// ManagedSeedSetStatusApplyConfiguration constructs an declarative configuration of the ManagedSeedSetStatus type for use with
-// apply.
-func ManagedSeedSetStatus() *ManagedSeedSetStatusApplyConfiguration {
- return &ManagedSeedSetStatusApplyConfiguration{}
-}
-
-// WithObservedGeneration sets the ObservedGeneration field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ObservedGeneration field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithObservedGeneration(value int64) *ManagedSeedSetStatusApplyConfiguration {
- b.ObservedGeneration = &value
- return b
-}
-
-// WithReplicas sets the Replicas field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Replicas field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithReplicas(value int32) *ManagedSeedSetStatusApplyConfiguration {
- b.Replicas = &value
- return b
-}
-
-// WithReadyReplicas sets the ReadyReplicas field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ReadyReplicas field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithReadyReplicas(value int32) *ManagedSeedSetStatusApplyConfiguration {
- b.ReadyReplicas = &value
- return b
-}
-
-// WithNextReplicaNumber sets the NextReplicaNumber field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the NextReplicaNumber field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithNextReplicaNumber(value int32) *ManagedSeedSetStatusApplyConfiguration {
- b.NextReplicaNumber = &value
- return b
-}
-
-// WithCurrentReplicas sets the CurrentReplicas field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the CurrentReplicas field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithCurrentReplicas(value int32) *ManagedSeedSetStatusApplyConfiguration {
- b.CurrentReplicas = &value
- return b
-}
-
-// WithUpdatedReplicas sets the UpdatedReplicas field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UpdatedReplicas field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithUpdatedReplicas(value int32) *ManagedSeedSetStatusApplyConfiguration {
- b.UpdatedReplicas = &value
- return b
-}
-
-// WithCurrentRevision sets the CurrentRevision field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the CurrentRevision field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithCurrentRevision(value string) *ManagedSeedSetStatusApplyConfiguration {
- b.CurrentRevision = &value
- return b
-}
-
-// WithUpdateRevision sets the UpdateRevision field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UpdateRevision field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithUpdateRevision(value string) *ManagedSeedSetStatusApplyConfiguration {
- b.UpdateRevision = &value
- return b
-}
-
-// WithCollisionCount sets the CollisionCount field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the CollisionCount field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithCollisionCount(value int32) *ManagedSeedSetStatusApplyConfiguration {
- b.CollisionCount = &value
- return b
-}
-
-// WithConditions adds the given value to the Conditions field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the Conditions field.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithConditions(values ...v1beta1.Condition) *ManagedSeedSetStatusApplyConfiguration {
- for i := range values {
- b.Conditions = append(b.Conditions, values[i])
- }
- return b
-}
-
-// WithPendingReplica sets the PendingReplica field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the PendingReplica field is set to the value of the last call.
-func (b *ManagedSeedSetStatusApplyConfiguration) WithPendingReplica(value *PendingReplicaApplyConfiguration) *ManagedSeedSetStatusApplyConfiguration {
- b.PendingReplica = value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedspec.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedspec.go
deleted file mode 100644
index d5afc989112..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedspec.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-// ManagedSeedSpecApplyConfiguration represents an declarative configuration of the ManagedSeedSpec type for use
-// with apply.
-type ManagedSeedSpecApplyConfiguration struct {
- Shoot *ShootApplyConfiguration `json:"shoot,omitempty"`
- Gardenlet *GardenletApplyConfiguration `json:"gardenlet,omitempty"`
-}
-
-// ManagedSeedSpecApplyConfiguration constructs an declarative configuration of the ManagedSeedSpec type for use with
-// apply.
-func ManagedSeedSpec() *ManagedSeedSpecApplyConfiguration {
- return &ManagedSeedSpecApplyConfiguration{}
-}
-
-// WithShoot sets the Shoot field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Shoot field is set to the value of the last call.
-func (b *ManagedSeedSpecApplyConfiguration) WithShoot(value *ShootApplyConfiguration) *ManagedSeedSpecApplyConfiguration {
- b.Shoot = value
- return b
-}
-
-// WithGardenlet sets the Gardenlet field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Gardenlet field is set to the value of the last call.
-func (b *ManagedSeedSpecApplyConfiguration) WithGardenlet(value *GardenletApplyConfiguration) *ManagedSeedSpecApplyConfiguration {
- b.Gardenlet = value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedstatus.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedstatus.go
deleted file mode 100644
index 097272ffd7e..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedstatus.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- v1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
-)
-
-// ManagedSeedStatusApplyConfiguration represents an declarative configuration of the ManagedSeedStatus type for use
-// with apply.
-type ManagedSeedStatusApplyConfiguration struct {
- Conditions []v1beta1.Condition `json:"conditions,omitempty"`
- ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
-}
-
-// ManagedSeedStatusApplyConfiguration constructs an declarative configuration of the ManagedSeedStatus type for use with
-// apply.
-func ManagedSeedStatus() *ManagedSeedStatusApplyConfiguration {
- return &ManagedSeedStatusApplyConfiguration{}
-}
-
-// WithConditions adds the given value to the Conditions field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the Conditions field.
-func (b *ManagedSeedStatusApplyConfiguration) WithConditions(values ...v1beta1.Condition) *ManagedSeedStatusApplyConfiguration {
- for i := range values {
- b.Conditions = append(b.Conditions, values[i])
- }
- return b
-}
-
-// WithObservedGeneration sets the ObservedGeneration field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ObservedGeneration field is set to the value of the last call.
-func (b *ManagedSeedStatusApplyConfiguration) WithObservedGeneration(value int64) *ManagedSeedStatusApplyConfiguration {
- b.ObservedGeneration = &value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedtemplate.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedtemplate.go
deleted file mode 100644
index 4ab011a1190..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/managedseedtemplate.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- "maps"
-
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- types "k8s.io/apimachinery/pkg/types"
- v1 "k8s.io/client-go/applyconfigurations/meta/v1"
-)
-
-// ManagedSeedTemplateApplyConfiguration represents an declarative configuration of the ManagedSeedTemplate type for use
-// with apply.
-type ManagedSeedTemplateApplyConfiguration struct {
- *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
- Spec *ManagedSeedSpecApplyConfiguration `json:"spec,omitempty"`
-}
-
-// ManagedSeedTemplateApplyConfiguration constructs an declarative configuration of the ManagedSeedTemplate type for use with
-// apply.
-func ManagedSeedTemplate() *ManagedSeedTemplateApplyConfiguration {
- return &ManagedSeedTemplateApplyConfiguration{}
-}
-
-// WithName sets the Name field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Name field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithName(value string) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Name = &value
- return b
-}
-
-// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the GenerateName field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithGenerateName(value string) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.GenerateName = &value
- return b
-}
-
-// WithNamespace sets the Namespace field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Namespace field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithNamespace(value string) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Namespace = &value
- return b
-}
-
-// WithUID sets the UID field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UID field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithUID(value types.UID) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.UID = &value
- return b
-}
-
-// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ResourceVersion field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithResourceVersion(value string) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.ResourceVersion = &value
- return b
-}
-
-// WithGeneration sets the Generation field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Generation field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithGeneration(value int64) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Generation = &value
- return b
-}
-
-// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the CreationTimestamp field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.CreationTimestamp = &value
- return b
-}
-
-// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionTimestamp = &value
- return b
-}
-
-// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionGracePeriodSeconds = &value
- return b
-}
-
-// WithLabels puts the entries into the Labels field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Labels field,
-// overwriting an existing map entries in Labels field with the same key.
-func (b *ManagedSeedTemplateApplyConfiguration) WithLabels(entries map[string]string) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Labels == nil && len(entries) > 0 {
- b.Labels = make(map[string]string, len(entries))
- }
- maps.Copy(b.Labels, entries)
- return b
-}
-
-// WithAnnotations puts the entries into the Annotations field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Annotations field,
-// overwriting an existing map entries in Annotations field with the same key.
-func (b *ManagedSeedTemplateApplyConfiguration) WithAnnotations(entries map[string]string) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Annotations == nil && len(entries) > 0 {
- b.Annotations = make(map[string]string, len(entries))
- }
- maps.Copy(b.Annotations, entries)
- return b
-}
-
-// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
-func (b *ManagedSeedTemplateApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- if values[i] == nil {
- panic("nil value passed to WithOwnerReferences")
- }
- b.OwnerReferences = append(b.OwnerReferences, *values[i])
- }
- return b
-}
-
-// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the Finalizers field.
-func (b *ManagedSeedTemplateApplyConfiguration) WithFinalizers(values ...string) *ManagedSeedTemplateApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- b.Finalizers = append(b.Finalizers, values[i])
- }
- return b
-}
-
-func (b *ManagedSeedTemplateApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
- if b.ObjectMetaApplyConfiguration == nil {
- b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
- }
-}
-
-// WithSpec sets the Spec field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Spec field is set to the value of the last call.
-func (b *ManagedSeedTemplateApplyConfiguration) WithSpec(value *ManagedSeedSpecApplyConfiguration) *ManagedSeedTemplateApplyConfiguration {
- b.Spec = value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/pendingreplica.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/pendingreplica.go
deleted file mode 100644
index ba9510b3f1a..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/pendingreplica.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- v1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1"
- v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-)
-
-// PendingReplicaApplyConfiguration represents an declarative configuration of the PendingReplica type for use
-// with apply.
-type PendingReplicaApplyConfiguration struct {
- Name *string `json:"name,omitempty"`
- Reason *v1alpha1.PendingReplicaReason `json:"reason,omitempty"`
- Since *v1.Time `json:"since,omitempty"`
- Retries *int32 `json:"retries,omitempty"`
-}
-
-// PendingReplicaApplyConfiguration constructs an declarative configuration of the PendingReplica type for use with
-// apply.
-func PendingReplica() *PendingReplicaApplyConfiguration {
- return &PendingReplicaApplyConfiguration{}
-}
-
-// WithName sets the Name field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Name field is set to the value of the last call.
-func (b *PendingReplicaApplyConfiguration) WithName(value string) *PendingReplicaApplyConfiguration {
- b.Name = &value
- return b
-}
-
-// WithReason sets the Reason field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Reason field is set to the value of the last call.
-func (b *PendingReplicaApplyConfiguration) WithReason(value v1alpha1.PendingReplicaReason) *PendingReplicaApplyConfiguration {
- b.Reason = &value
- return b
-}
-
-// WithSince sets the Since field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Since field is set to the value of the last call.
-func (b *PendingReplicaApplyConfiguration) WithSince(value v1.Time) *PendingReplicaApplyConfiguration {
- b.Since = &value
- return b
-}
-
-// WithRetries sets the Retries field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Retries field is set to the value of the last call.
-func (b *PendingReplicaApplyConfiguration) WithRetries(value int32) *PendingReplicaApplyConfiguration {
- b.Retries = &value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/rollingupdatestrategy.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/rollingupdatestrategy.go
deleted file mode 100644
index 7be8b4b7d6e..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/rollingupdatestrategy.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-// RollingUpdateStrategyApplyConfiguration represents an declarative configuration of the RollingUpdateStrategy type for use
-// with apply.
-type RollingUpdateStrategyApplyConfiguration struct {
- Partition *int32 `json:"partition,omitempty"`
-}
-
-// RollingUpdateStrategyApplyConfiguration constructs an declarative configuration of the RollingUpdateStrategy type for use with
-// apply.
-func RollingUpdateStrategy() *RollingUpdateStrategyApplyConfiguration {
- return &RollingUpdateStrategyApplyConfiguration{}
-}
-
-// WithPartition sets the Partition field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Partition field is set to the value of the last call.
-func (b *RollingUpdateStrategyApplyConfiguration) WithPartition(value int32) *RollingUpdateStrategyApplyConfiguration {
- b.Partition = &value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/shoot.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/shoot.go
deleted file mode 100644
index 7526f8352d7..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/shoot.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-// ShootApplyConfiguration represents an declarative configuration of the Shoot type for use
-// with apply.
-type ShootApplyConfiguration struct {
- Name *string `json:"name,omitempty"`
-}
-
-// ShootApplyConfiguration constructs an declarative configuration of the Shoot type for use with
-// apply.
-func Shoot() *ShootApplyConfiguration {
- return &ShootApplyConfiguration{}
-}
-
-// WithName sets the Name field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Name field is set to the value of the last call.
-func (b *ShootApplyConfiguration) WithName(value string) *ShootApplyConfiguration {
- b.Name = &value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/updatestrategy.go b/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/updatestrategy.go
deleted file mode 100644
index 3876e366d33..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1/updatestrategy.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- v1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1"
-)
-
-// UpdateStrategyApplyConfiguration represents an declarative configuration of the UpdateStrategy type for use
-// with apply.
-type UpdateStrategyApplyConfiguration struct {
- Type *v1alpha1.UpdateStrategyType `json:"type,omitempty"`
- RollingUpdate *RollingUpdateStrategyApplyConfiguration `json:"rollingUpdate,omitempty"`
-}
-
-// UpdateStrategyApplyConfiguration constructs an declarative configuration of the UpdateStrategy type for use with
-// apply.
-func UpdateStrategy() *UpdateStrategyApplyConfiguration {
- return &UpdateStrategyApplyConfiguration{}
-}
-
-// WithType sets the Type field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Type field is set to the value of the last call.
-func (b *UpdateStrategyApplyConfiguration) WithType(value v1alpha1.UpdateStrategyType) *UpdateStrategyApplyConfiguration {
- b.Type = &value
- return b
-}
-
-// WithRollingUpdate sets the RollingUpdate field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the RollingUpdate field is set to the value of the last call.
-func (b *UpdateStrategyApplyConfiguration) WithRollingUpdate(value *RollingUpdateStrategyApplyConfiguration) *UpdateStrategyApplyConfiguration {
- b.RollingUpdate = value
- return b
-}
diff --git a/pkg/client/seedmanagement/applyconfiguration/utils.go b/pkg/client/seedmanagement/applyconfiguration/utils.go
deleted file mode 100644
index 2cc6a227229..00000000000
--- a/pkg/client/seedmanagement/applyconfiguration/utils.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package applyconfiguration
-
-import (
- v1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1"
- seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/client/seedmanagement/applyconfiguration/seedmanagement/v1alpha1"
- schema "k8s.io/apimachinery/pkg/runtime/schema"
-)
-
-// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no
-// apply configuration type exists for the given GroupVersionKind.
-func ForKind(kind schema.GroupVersionKind) any {
- switch kind {
- // Group=seedmanagement.gardener.cloud, Version=v1alpha1
- case v1alpha1.SchemeGroupVersion.WithKind("GardenletConfig"):
- return &seedmanagementv1alpha1.GardenletApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("GardenletDeployment"):
- return &seedmanagementv1alpha1.GardenletDeploymentApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("Image"):
- return &seedmanagementv1alpha1.ImageApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("ManagedSeed"):
- return &seedmanagementv1alpha1.ManagedSeedApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("ManagedSeedSet"):
- return &seedmanagementv1alpha1.ManagedSeedSetApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("ManagedSeedSetSpec"):
- return &seedmanagementv1alpha1.ManagedSeedSetSpecApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("ManagedSeedSetStatus"):
- return &seedmanagementv1alpha1.ManagedSeedSetStatusApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("ManagedSeedSpec"):
- return &seedmanagementv1alpha1.ManagedSeedSpecApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("ManagedSeedStatus"):
- return &seedmanagementv1alpha1.ManagedSeedStatusApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("ManagedSeedTemplate"):
- return &seedmanagementv1alpha1.ManagedSeedTemplateApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("PendingReplica"):
- return &seedmanagementv1alpha1.PendingReplicaApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("RollingUpdateStrategy"):
- return &seedmanagementv1alpha1.RollingUpdateStrategyApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("Shoot"):
- return &seedmanagementv1alpha1.ShootApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("UpdateStrategy"):
- return &seedmanagementv1alpha1.UpdateStrategyApplyConfiguration{}
-
- }
- return nil
-}
diff --git a/pkg/client/settings/applyconfiguration/internal/internal.go b/pkg/client/settings/applyconfiguration/internal/internal.go
deleted file mode 100644
index 6b06d7c5835..00000000000
--- a/pkg/client/settings/applyconfiguration/internal/internal.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package internal
-
-import (
- "fmt"
- "sync"
-
- typed "sigs.k8s.io/structured-merge-diff/v4/typed"
-)
-
-func Parser() *typed.Parser {
- parserOnce.Do(func() {
- var err error
- parser, err = typed.NewParser(schemaYAML)
- if err != nil {
- panic(fmt.Sprintf("Failed to parse schema: %v", err))
- }
- })
- return parser
-}
-
-var parserOnce sync.Once
-var parser *typed.Parser
-var schemaYAML = typed.YAMLObject(`types:
-- name: __untyped_atomic_
- scalar: untyped
- list:
- elementType:
- namedType: __untyped_atomic_
- elementRelationship: atomic
- map:
- elementType:
- namedType: __untyped_atomic_
- elementRelationship: atomic
-- name: __untyped_deduced_
- scalar: untyped
- list:
- elementType:
- namedType: __untyped_atomic_
- elementRelationship: atomic
- map:
- elementType:
- namedType: __untyped_deduced_
- elementRelationship: separable
-`)
diff --git a/pkg/client/settings/applyconfiguration/settings/v1alpha1/clusteropenidconnectpreset.go b/pkg/client/settings/applyconfiguration/settings/v1alpha1/clusteropenidconnectpreset.go
deleted file mode 100644
index 3375c19abf2..00000000000
--- a/pkg/client/settings/applyconfiguration/settings/v1alpha1/clusteropenidconnectpreset.go
+++ /dev/null
@@ -1,195 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- "maps"
-
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- types "k8s.io/apimachinery/pkg/types"
- v1 "k8s.io/client-go/applyconfigurations/meta/v1"
-)
-
-// ClusterOpenIDConnectPresetApplyConfiguration represents an declarative configuration of the ClusterOpenIDConnectPreset type for use
-// with apply.
-type ClusterOpenIDConnectPresetApplyConfiguration struct {
- v1.TypeMetaApplyConfiguration `json:",inline"`
- *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
- Spec *ClusterOpenIDConnectPresetSpecApplyConfiguration `json:"spec,omitempty"`
-}
-
-// ClusterOpenIDConnectPreset constructs an declarative configuration of the ClusterOpenIDConnectPreset type for use with
-// apply.
-func ClusterOpenIDConnectPreset(name string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b := &ClusterOpenIDConnectPresetApplyConfiguration{}
- b.WithName(name)
- b.WithKind("ClusterOpenIDConnectPreset")
- b.WithAPIVersion("settings.gardener.cloud/v1alpha1")
- return b
-}
-
-// WithKind sets the Kind field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Kind field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithKind(value string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.Kind = &value
- return b
-}
-
-// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the APIVersion field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithAPIVersion(value string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.APIVersion = &value
- return b
-}
-
-// WithName sets the Name field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Name field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithName(value string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Name = &value
- return b
-}
-
-// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the GenerateName field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithGenerateName(value string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.GenerateName = &value
- return b
-}
-
-// WithNamespace sets the Namespace field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Namespace field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithNamespace(value string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Namespace = &value
- return b
-}
-
-// WithUID sets the UID field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UID field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithUID(value types.UID) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.UID = &value
- return b
-}
-
-// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ResourceVersion field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithResourceVersion(value string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.ResourceVersion = &value
- return b
-}
-
-// WithGeneration sets the Generation field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Generation field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithGeneration(value int64) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Generation = &value
- return b
-}
-
-// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the CreationTimestamp field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.CreationTimestamp = &value
- return b
-}
-
-// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionTimestamp = &value
- return b
-}
-
-// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionGracePeriodSeconds = &value
- return b
-}
-
-// WithLabels puts the entries into the Labels field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Labels field,
-// overwriting an existing map entries in Labels field with the same key.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithLabels(entries map[string]string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Labels == nil && len(entries) > 0 {
- b.Labels = make(map[string]string, len(entries))
- }
- maps.Copy(b.Labels, entries)
- return b
-}
-
-// WithAnnotations puts the entries into the Annotations field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Annotations field,
-// overwriting an existing map entries in Annotations field with the same key.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithAnnotations(entries map[string]string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Annotations == nil && len(entries) > 0 {
- b.Annotations = make(map[string]string, len(entries))
- }
- maps.Copy(b.Annotations, entries)
- return b
-}
-
-// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- if values[i] == nil {
- panic("nil value passed to WithOwnerReferences")
- }
- b.OwnerReferences = append(b.OwnerReferences, *values[i])
- }
- return b
-}
-
-// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the Finalizers field.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithFinalizers(values ...string) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- b.Finalizers = append(b.Finalizers, values[i])
- }
- return b
-}
-
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
- if b.ObjectMetaApplyConfiguration == nil {
- b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
- }
-}
-
-// WithSpec sets the Spec field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Spec field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetApplyConfiguration) WithSpec(value *ClusterOpenIDConnectPresetSpecApplyConfiguration) *ClusterOpenIDConnectPresetApplyConfiguration {
- b.Spec = value
- return b
-}
diff --git a/pkg/client/settings/applyconfiguration/settings/v1alpha1/clusteropenidconnectpresetspec.go b/pkg/client/settings/applyconfiguration/settings/v1alpha1/clusteropenidconnectpresetspec.go
deleted file mode 100644
index da870d4de5d..00000000000
--- a/pkg/client/settings/applyconfiguration/settings/v1alpha1/clusteropenidconnectpresetspec.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-)
-
-// ClusterOpenIDConnectPresetSpecApplyConfiguration represents an declarative configuration of the ClusterOpenIDConnectPresetSpec type for use
-// with apply.
-type ClusterOpenIDConnectPresetSpecApplyConfiguration struct {
- OpenIDConnectPresetSpecApplyConfiguration `json:",inline"`
- ProjectSelector *v1.LabelSelector `json:"projectSelector,omitempty"`
-}
-
-// ClusterOpenIDConnectPresetSpecApplyConfiguration constructs an declarative configuration of the ClusterOpenIDConnectPresetSpec type for use with
-// apply.
-func ClusterOpenIDConnectPresetSpec() *ClusterOpenIDConnectPresetSpecApplyConfiguration {
- return &ClusterOpenIDConnectPresetSpecApplyConfiguration{}
-}
-
-// WithServer sets the Server field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Server field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetSpecApplyConfiguration) WithServer(value *KubeAPIServerOpenIDConnectApplyConfiguration) *ClusterOpenIDConnectPresetSpecApplyConfiguration {
- b.Server = value
- return b
-}
-
-// WithClient sets the Client field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Client field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetSpecApplyConfiguration) WithClient(value *OpenIDConnectClientAuthenticationApplyConfiguration) *ClusterOpenIDConnectPresetSpecApplyConfiguration {
- b.Client = value
- return b
-}
-
-// WithShootSelector sets the ShootSelector field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ShootSelector field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetSpecApplyConfiguration) WithShootSelector(value v1.LabelSelector) *ClusterOpenIDConnectPresetSpecApplyConfiguration {
- b.ShootSelector = &value
- return b
-}
-
-// WithWeight sets the Weight field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Weight field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetSpecApplyConfiguration) WithWeight(value int32) *ClusterOpenIDConnectPresetSpecApplyConfiguration {
- b.Weight = &value
- return b
-}
-
-// WithProjectSelector sets the ProjectSelector field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ProjectSelector field is set to the value of the last call.
-func (b *ClusterOpenIDConnectPresetSpecApplyConfiguration) WithProjectSelector(value v1.LabelSelector) *ClusterOpenIDConnectPresetSpecApplyConfiguration {
- b.ProjectSelector = &value
- return b
-}
diff --git a/pkg/client/settings/applyconfiguration/settings/v1alpha1/kubeapiserveropenidconnect.go b/pkg/client/settings/applyconfiguration/settings/v1alpha1/kubeapiserveropenidconnect.go
deleted file mode 100644
index 4da7c566e8c..00000000000
--- a/pkg/client/settings/applyconfiguration/settings/v1alpha1/kubeapiserveropenidconnect.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import "maps"
-
-// KubeAPIServerOpenIDConnectApplyConfiguration represents an declarative configuration of the KubeAPIServerOpenIDConnect type for use
-// with apply.
-type KubeAPIServerOpenIDConnectApplyConfiguration struct {
- CABundle *string `json:"caBundle,omitempty"`
- ClientID *string `json:"clientID,omitempty"`
- GroupsClaim *string `json:"groupsClaim,omitempty"`
- GroupsPrefix *string `json:"groupsPrefix,omitempty"`
- IssuerURL *string `json:"issuerURL,omitempty"`
- RequiredClaims map[string]string `json:"requiredClaims,omitempty"`
- SigningAlgs []string `json:"signingAlgs,omitempty"`
- UsernameClaim *string `json:"usernameClaim,omitempty"`
- UsernamePrefix *string `json:"usernamePrefix,omitempty"`
-}
-
-// KubeAPIServerOpenIDConnectApplyConfiguration constructs an declarative configuration of the KubeAPIServerOpenIDConnect type for use with
-// apply.
-func KubeAPIServerOpenIDConnect() *KubeAPIServerOpenIDConnectApplyConfiguration {
- return &KubeAPIServerOpenIDConnectApplyConfiguration{}
-}
-
-// WithCABundle sets the CABundle field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the CABundle field is set to the value of the last call.
-func (b *KubeAPIServerOpenIDConnectApplyConfiguration) WithCABundle(value string) *KubeAPIServerOpenIDConnectApplyConfiguration {
- b.CABundle = &value
- return b
-}
-
-// WithClientID sets the ClientID field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ClientID field is set to the value of the last call.
-func (b *KubeAPIServerOpenIDConnectApplyConfiguration) WithClientID(value string) *KubeAPIServerOpenIDConnectApplyConfiguration {
- b.ClientID = &value
- return b
-}
-
-// WithGroupsClaim sets the GroupsClaim field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the GroupsClaim field is set to the value of the last call.
-func (b *KubeAPIServerOpenIDConnectApplyConfiguration) WithGroupsClaim(value string) *KubeAPIServerOpenIDConnectApplyConfiguration {
- b.GroupsClaim = &value
- return b
-}
-
-// WithGroupsPrefix sets the GroupsPrefix field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the GroupsPrefix field is set to the value of the last call.
-func (b *KubeAPIServerOpenIDConnectApplyConfiguration) WithGroupsPrefix(value string) *KubeAPIServerOpenIDConnectApplyConfiguration {
- b.GroupsPrefix = &value
- return b
-}
-
-// WithIssuerURL sets the IssuerURL field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the IssuerURL field is set to the value of the last call.
-func (b *KubeAPIServerOpenIDConnectApplyConfiguration) WithIssuerURL(value string) *KubeAPIServerOpenIDConnectApplyConfiguration {
- b.IssuerURL = &value
- return b
-}
-
-// WithRequiredClaims puts the entries into the RequiredClaims field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the RequiredClaims field,
-// overwriting an existing map entries in RequiredClaims field with the same key.
-func (b *KubeAPIServerOpenIDConnectApplyConfiguration) WithRequiredClaims(entries map[string]string) *KubeAPIServerOpenIDConnectApplyConfiguration {
- if b.RequiredClaims == nil && len(entries) > 0 {
- b.RequiredClaims = make(map[string]string, len(entries))
- }
- maps.Copy(b.RequiredClaims, entries)
- return b
-}
-
-// WithSigningAlgs adds the given value to the SigningAlgs field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the SigningAlgs field.
-func (b *KubeAPIServerOpenIDConnectApplyConfiguration) WithSigningAlgs(values ...string) *KubeAPIServerOpenIDConnectApplyConfiguration {
- for i := range values {
- b.SigningAlgs = append(b.SigningAlgs, values[i])
- }
- return b
-}
-
-// WithUsernameClaim sets the UsernameClaim field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UsernameClaim field is set to the value of the last call.
-func (b *KubeAPIServerOpenIDConnectApplyConfiguration) WithUsernameClaim(value string) *KubeAPIServerOpenIDConnectApplyConfiguration {
- b.UsernameClaim = &value
- return b
-}
-
-// WithUsernamePrefix sets the UsernamePrefix field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UsernamePrefix field is set to the value of the last call.
-func (b *KubeAPIServerOpenIDConnectApplyConfiguration) WithUsernamePrefix(value string) *KubeAPIServerOpenIDConnectApplyConfiguration {
- b.UsernamePrefix = &value
- return b
-}
diff --git a/pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectclientauthentication.go b/pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectclientauthentication.go
deleted file mode 100644
index 292c361e649..00000000000
--- a/pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectclientauthentication.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import "maps"
-
-// OpenIDConnectClientAuthenticationApplyConfiguration represents an declarative configuration of the OpenIDConnectClientAuthentication type for use
-// with apply.
-type OpenIDConnectClientAuthenticationApplyConfiguration struct {
- Secret *string `json:"secret,omitempty"`
- ExtraConfig map[string]string `json:"extraConfig,omitempty"`
-}
-
-// OpenIDConnectClientAuthenticationApplyConfiguration constructs an declarative configuration of the OpenIDConnectClientAuthentication type for use with
-// apply.
-func OpenIDConnectClientAuthentication() *OpenIDConnectClientAuthenticationApplyConfiguration {
- return &OpenIDConnectClientAuthenticationApplyConfiguration{}
-}
-
-// WithSecret sets the Secret field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Secret field is set to the value of the last call.
-func (b *OpenIDConnectClientAuthenticationApplyConfiguration) WithSecret(value string) *OpenIDConnectClientAuthenticationApplyConfiguration {
- b.Secret = &value
- return b
-}
-
-// WithExtraConfig puts the entries into the ExtraConfig field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the ExtraConfig field,
-// overwriting an existing map entries in ExtraConfig field with the same key.
-func (b *OpenIDConnectClientAuthenticationApplyConfiguration) WithExtraConfig(entries map[string]string) *OpenIDConnectClientAuthenticationApplyConfiguration {
- if b.ExtraConfig == nil && len(entries) > 0 {
- b.ExtraConfig = make(map[string]string, len(entries))
- }
- maps.Copy(b.ExtraConfig, entries)
- return b
-}
diff --git a/pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectpreset.go b/pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectpreset.go
deleted file mode 100644
index 697066c318a..00000000000
--- a/pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectpreset.go
+++ /dev/null
@@ -1,196 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- "maps"
-
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- types "k8s.io/apimachinery/pkg/types"
- v1 "k8s.io/client-go/applyconfigurations/meta/v1"
-)
-
-// OpenIDConnectPresetApplyConfiguration represents an declarative configuration of the OpenIDConnectPreset type for use
-// with apply.
-type OpenIDConnectPresetApplyConfiguration struct {
- v1.TypeMetaApplyConfiguration `json:",inline"`
- *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
- Spec *OpenIDConnectPresetSpecApplyConfiguration `json:"spec,omitempty"`
-}
-
-// OpenIDConnectPreset constructs an declarative configuration of the OpenIDConnectPreset type for use with
-// apply.
-func OpenIDConnectPreset(name, namespace string) *OpenIDConnectPresetApplyConfiguration {
- b := &OpenIDConnectPresetApplyConfiguration{}
- b.WithName(name)
- b.WithNamespace(namespace)
- b.WithKind("OpenIDConnectPreset")
- b.WithAPIVersion("settings.gardener.cloud/v1alpha1")
- return b
-}
-
-// WithKind sets the Kind field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Kind field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithKind(value string) *OpenIDConnectPresetApplyConfiguration {
- b.Kind = &value
- return b
-}
-
-// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the APIVersion field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithAPIVersion(value string) *OpenIDConnectPresetApplyConfiguration {
- b.APIVersion = &value
- return b
-}
-
-// WithName sets the Name field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Name field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithName(value string) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Name = &value
- return b
-}
-
-// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the GenerateName field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithGenerateName(value string) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.GenerateName = &value
- return b
-}
-
-// WithNamespace sets the Namespace field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Namespace field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithNamespace(value string) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Namespace = &value
- return b
-}
-
-// WithUID sets the UID field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the UID field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithUID(value types.UID) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.UID = &value
- return b
-}
-
-// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ResourceVersion field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithResourceVersion(value string) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.ResourceVersion = &value
- return b
-}
-
-// WithGeneration sets the Generation field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Generation field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithGeneration(value int64) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.Generation = &value
- return b
-}
-
-// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the CreationTimestamp field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithCreationTimestamp(value metav1.Time) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.CreationTimestamp = &value
- return b
-}
-
-// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionTimestamp = &value
- return b
-}
-
-// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- b.DeletionGracePeriodSeconds = &value
- return b
-}
-
-// WithLabels puts the entries into the Labels field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Labels field,
-// overwriting an existing map entries in Labels field with the same key.
-func (b *OpenIDConnectPresetApplyConfiguration) WithLabels(entries map[string]string) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Labels == nil && len(entries) > 0 {
- b.Labels = make(map[string]string, len(entries))
- }
- maps.Copy(b.Labels, entries)
- return b
-}
-
-// WithAnnotations puts the entries into the Annotations field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, the entries provided by each call will be put on the Annotations field,
-// overwriting an existing map entries in Annotations field with the same key.
-func (b *OpenIDConnectPresetApplyConfiguration) WithAnnotations(entries map[string]string) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- if b.Annotations == nil && len(entries) > 0 {
- b.Annotations = make(map[string]string, len(entries))
- }
- maps.Copy(b.Annotations, entries)
- return b
-}
-
-// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
-func (b *OpenIDConnectPresetApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- if values[i] == nil {
- panic("nil value passed to WithOwnerReferences")
- }
- b.OwnerReferences = append(b.OwnerReferences, *values[i])
- }
- return b
-}
-
-// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
-// and returns the receiver, so that objects can be build by chaining "With" function invocations.
-// If called multiple times, values provided by each call will be appended to the Finalizers field.
-func (b *OpenIDConnectPresetApplyConfiguration) WithFinalizers(values ...string) *OpenIDConnectPresetApplyConfiguration {
- b.ensureObjectMetaApplyConfigurationExists()
- for i := range values {
- b.Finalizers = append(b.Finalizers, values[i])
- }
- return b
-}
-
-func (b *OpenIDConnectPresetApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
- if b.ObjectMetaApplyConfiguration == nil {
- b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
- }
-}
-
-// WithSpec sets the Spec field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Spec field is set to the value of the last call.
-func (b *OpenIDConnectPresetApplyConfiguration) WithSpec(value *OpenIDConnectPresetSpecApplyConfiguration) *OpenIDConnectPresetApplyConfiguration {
- b.Spec = value
- return b
-}
diff --git a/pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectpresetspec.go b/pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectpresetspec.go
deleted file mode 100644
index 799790d7534..00000000000
--- a/pkg/client/settings/applyconfiguration/settings/v1alpha1/openidconnectpresetspec.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-)
-
-// OpenIDConnectPresetSpecApplyConfiguration represents an declarative configuration of the OpenIDConnectPresetSpec type for use
-// with apply.
-type OpenIDConnectPresetSpecApplyConfiguration struct {
- Server *KubeAPIServerOpenIDConnectApplyConfiguration `json:"server,omitempty"`
- Client *OpenIDConnectClientAuthenticationApplyConfiguration `json:"client,omitempty"`
- ShootSelector *v1.LabelSelector `json:"shootSelector,omitempty"`
- Weight *int32 `json:"weight,omitempty"`
-}
-
-// OpenIDConnectPresetSpecApplyConfiguration constructs an declarative configuration of the OpenIDConnectPresetSpec type for use with
-// apply.
-func OpenIDConnectPresetSpec() *OpenIDConnectPresetSpecApplyConfiguration {
- return &OpenIDConnectPresetSpecApplyConfiguration{}
-}
-
-// WithServer sets the Server field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Server field is set to the value of the last call.
-func (b *OpenIDConnectPresetSpecApplyConfiguration) WithServer(value *KubeAPIServerOpenIDConnectApplyConfiguration) *OpenIDConnectPresetSpecApplyConfiguration {
- b.Server = value
- return b
-}
-
-// WithClient sets the Client field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Client field is set to the value of the last call.
-func (b *OpenIDConnectPresetSpecApplyConfiguration) WithClient(value *OpenIDConnectClientAuthenticationApplyConfiguration) *OpenIDConnectPresetSpecApplyConfiguration {
- b.Client = value
- return b
-}
-
-// WithShootSelector sets the ShootSelector field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the ShootSelector field is set to the value of the last call.
-func (b *OpenIDConnectPresetSpecApplyConfiguration) WithShootSelector(value v1.LabelSelector) *OpenIDConnectPresetSpecApplyConfiguration {
- b.ShootSelector = &value
- return b
-}
-
-// WithWeight sets the Weight field in the declarative configuration to the given value
-// and returns the receiver, so that objects can be built by chaining "With" function invocations.
-// If called multiple times, the Weight field is set to the value of the last call.
-func (b *OpenIDConnectPresetSpecApplyConfiguration) WithWeight(value int32) *OpenIDConnectPresetSpecApplyConfiguration {
- b.Weight = &value
- return b
-}
diff --git a/pkg/client/settings/applyconfiguration/utils.go b/pkg/client/settings/applyconfiguration/utils.go
deleted file mode 100644
index 6314caad932..00000000000
--- a/pkg/client/settings/applyconfiguration/utils.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated by applyconfiguration-gen. DO NOT EDIT.
-
-package applyconfiguration
-
-import (
- v1alpha1 "github.com/gardener/gardener/pkg/apis/settings/v1alpha1"
- settingsv1alpha1 "github.com/gardener/gardener/pkg/client/settings/applyconfiguration/settings/v1alpha1"
- schema "k8s.io/apimachinery/pkg/runtime/schema"
-)
-
-// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no
-// apply configuration type exists for the given GroupVersionKind.
-func ForKind(kind schema.GroupVersionKind) any {
- switch kind {
- // Group=settings.gardener.cloud, Version=v1alpha1
- case v1alpha1.SchemeGroupVersion.WithKind("ClusterOpenIDConnectPreset"):
- return &settingsv1alpha1.ClusterOpenIDConnectPresetApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("ClusterOpenIDConnectPresetSpec"):
- return &settingsv1alpha1.ClusterOpenIDConnectPresetSpecApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("KubeAPIServerOpenIDConnect"):
- return &settingsv1alpha1.KubeAPIServerOpenIDConnectApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("OpenIDConnectClientAuthentication"):
- return &settingsv1alpha1.OpenIDConnectClientAuthenticationApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("OpenIDConnectPreset"):
- return &settingsv1alpha1.OpenIDConnectPresetApplyConfiguration{}
- case v1alpha1.SchemeGroupVersion.WithKind("OpenIDConnectPresetSpec"):
- return &settingsv1alpha1.OpenIDConnectPresetSpecApplyConfiguration{}
-
- }
- return nil
-}
diff --git a/pkg/component/autoscaling/vpa/templates/crd-autoscaling.k8s.io_verticalpodautoscalercheckpoints.yaml b/pkg/component/autoscaling/vpa/templates/crd-autoscaling.k8s.io_verticalpodautoscalercheckpoints.yaml
index 4266f366c00..2203cba9f2d 100644
--- a/pkg/component/autoscaling/vpa/templates/crd-autoscaling.k8s.io_verticalpodautoscalercheckpoints.yaml
+++ b/pkg/component/autoscaling/vpa/templates/crd-autoscaling.k8s.io_verticalpodautoscalercheckpoints.yaml
@@ -5,7 +5,7 @@ metadata:
annotations:
resources.gardener.cloud/keep-object: "true"
api-approved.kubernetes.io: https://github.com/kubernetes/kubernetes/pull/63797
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: verticalpodautoscalercheckpoints.autoscaling.k8s.io
spec:
group: autoscaling.k8s.io
diff --git a/pkg/component/autoscaling/vpa/templates/crd-autoscaling.k8s.io_verticalpodautoscalers.yaml b/pkg/component/autoscaling/vpa/templates/crd-autoscaling.k8s.io_verticalpodautoscalers.yaml
index 8e94ce1ca28..191fe201933 100644
--- a/pkg/component/autoscaling/vpa/templates/crd-autoscaling.k8s.io_verticalpodautoscalers.yaml
+++ b/pkg/component/autoscaling/vpa/templates/crd-autoscaling.k8s.io_verticalpodautoscalers.yaml
@@ -5,7 +5,7 @@ metadata:
annotations:
resources.gardener.cloud/keep-object: "true"
api-approved.kubernetes.io: https://github.com/kubernetes/kubernetes/pull/63797
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: verticalpodautoscalers.autoscaling.k8s.io
spec:
group: autoscaling.k8s.io
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_backupbuckets.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_backupbuckets.yaml
index f56520169b6..71ee9569aeb 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_backupbuckets.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_backupbuckets.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: backupbuckets.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_backupentries.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_backupentries.yaml
index b03875890a8..322b116e836 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_backupentries.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_backupentries.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: backupentries.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_bastions.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_bastions.yaml
index a670a7007f6..6ae72f0e9ff 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_bastions.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_bastions.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: bastions.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_clusters.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_clusters.yaml
index 9b5611899d0..c670d2421b3 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_clusters.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_clusters.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusters.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_containerruntimes.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_containerruntimes.yaml
index 38f11e81ac5..a635fc787aa 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_containerruntimes.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_containerruntimes.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: containerruntimes.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_controlplanes.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_controlplanes.yaml
index 81f25012c68..29fcbba6f78 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_controlplanes.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_controlplanes.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: controlplanes.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_dnsrecords.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_dnsrecords.yaml
index f5bc16037ee..0e75b35b7ea 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_dnsrecords.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_dnsrecords.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: dnsrecords.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_extensions.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_extensions.yaml
index 1bcdad48489..e265f7b7481 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_extensions.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_extensions.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: extensions.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_infrastructures.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_infrastructures.yaml
index 0cfebbcfb0e..a88b01db554 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_infrastructures.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_infrastructures.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: infrastructures.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_networks.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_networks.yaml
index 33b6c9ea4b2..f5cc01ac850 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_networks.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_networks.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: networks.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_operatingsystemconfigs.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_operatingsystemconfigs.yaml
index 3c35391fe7c..e870cf9af4d 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_operatingsystemconfigs.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_operatingsystemconfigs.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: operatingsystemconfigs.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
diff --git a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_workers.yaml b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_workers.yaml
index 8981af70b25..2082d1997fb 100644
--- a/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_workers.yaml
+++ b/pkg/component/extensions/crds/assets/crd-extensions.gardener.cloud_workers.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: workers.extensions.gardener.cloud
spec:
group: extensions.gardener.cloud
@@ -650,9 +650,8 @@ spec:
a node.
type: string
timeAdded:
- description: |-
- TimeAdded represents the time at which the taint was added.
- It is only written for NoExecute taints.
+ description: TimeAdded represents the time at which the
+ taint was added.
format: date-time
type: string
value:
diff --git a/pkg/component/extensions/operatingsystemconfig/original/components/nodeagent/rbac_test.go b/pkg/component/extensions/operatingsystemconfig/original/components/nodeagent/rbac_test.go
index 575e5205a43..f09301db120 100644
--- a/pkg/component/extensions/operatingsystemconfig/original/components/nodeagent/rbac_test.go
+++ b/pkg/component/extensions/operatingsystemconfig/original/components/nodeagent/rbac_test.go
@@ -26,7 +26,6 @@ var _ = Describe("RBAC", func() {
clusterRoleBindingNodeBootstrapperYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
- creationTimestamp: null
name: system:node-bootstrapper
roleRef:
apiGroup: rbac.authorization.k8s.io
@@ -41,7 +40,6 @@ subjects:
clusterRoleBindingNodeClientYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
- creationTimestamp: null
name: system:certificates.k8s.io:certificatesigningrequests:nodeclient
roleRef:
apiGroup: rbac.authorization.k8s.io
@@ -55,7 +53,6 @@ subjects:
clusterRoleBindingSelfNodeClientYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
- creationTimestamp: null
name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
roleRef:
apiGroup: rbac.authorization.k8s.io
diff --git a/pkg/component/extensions/operatingsystemconfig/original/components/nodeagent/secrets_test.go b/pkg/component/extensions/operatingsystemconfig/original/components/nodeagent/secrets_test.go
index ada4895fe65..1560cf8e77e 100644
--- a/pkg/component/extensions/operatingsystemconfig/original/components/nodeagent/secrets_test.go
+++ b/pkg/component/extensions/operatingsystemconfig/original/components/nodeagent/secrets_test.go
@@ -109,7 +109,7 @@ var _ = Describe("Secrets", func() {
Name: secretName,
Namespace: "kube-system",
Annotations: map[string]string{
- "checksum/data-script": "a3efca387130b4a0291595c1608d80cad758ca95f71901f1fc91b0d74847c0ff",
+ "checksum/data-script": "e92163ba634e290c2e13de35a778007114e201e168c0a27149d05ab5592e4d36",
},
Labels: map[string]string{
"gardener.cloud/role": "operating-system-config",
@@ -118,8 +118,7 @@ var _ = Describe("Secrets", func() {
},
Data: map[string][]byte{"osc.yaml": []byte(`apiVersion: extensions.gardener.cloud/v1alpha1
kind: OperatingSystemConfig
-metadata:
- creationTimestamp: null
+metadata: {}
spec:
criConfig:
containerd:
diff --git a/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/config_test.go b/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/config_test.go
index b218ed7f856..7e087c3cceb 100644
--- a/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/config_test.go
+++ b/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/config_test.go
@@ -250,7 +250,6 @@ contexts:
name: shoot
current-context: shoot
kind: Config
-preferences: {}
users:
- name: shoot
user:
diff --git a/pkg/component/gardener/access/access_test.go b/pkg/component/gardener/access/access_test.go
index a411d7c4a80..e0ff81fae83 100644
--- a/pkg/component/gardener/access/access_test.go
+++ b/pkg/component/gardener/access/access_test.go
@@ -197,7 +197,6 @@ contexts:
name: ` + namespace + `
current-context: ` + namespace + `
kind: Config
-preferences: {}
users:
- name: ` + namespace + `
user: {}
@@ -231,7 +230,6 @@ contexts:
name: ` + namespace + `
current-context: ` + namespace + `
kind: Config
-preferences: {}
users:
- name: ` + namespace + `
user: {}
diff --git a/pkg/component/gardener/apiserver/apiserver_test.go b/pkg/component/gardener/apiserver/apiserver_test.go
index 0de2538363a..744b8632ca6 100644
--- a/pkg/component/gardener/apiserver/apiserver_test.go
+++ b/pkg/component/gardener/apiserver/apiserver_test.go
@@ -269,7 +269,7 @@ var _ = Describe("GardenerAPIServer", func() {
"role": "apiserver",
},
Annotations: map[string]string{
- "reference.resources.gardener.cloud/configmap-0e4e3fd5": "gardener-apiserver-audit-policy-config-f5b578b4",
+ "reference.resources.gardener.cloud/configmap-1b2d9b42": "gardener-apiserver-audit-policy-config-1e270362",
"reference.resources.gardener.cloud/configmap-6e5f123b": "gardener-apiserver-admission-config-07c5248a",
"reference.resources.gardener.cloud/secret-9dca243c": "shoot-access-gardener-apiserver",
"reference.resources.gardener.cloud/secret-47fc132b": "gardener-apiserver-admission-kubeconfigs-e3b0c442",
@@ -309,7 +309,7 @@ var _ = Describe("GardenerAPIServer", func() {
"networking.resources.gardener.cloud/to-virtual-garden-kube-apiserver-tcp-443": "allowed",
},
Annotations: map[string]string{
- "reference.resources.gardener.cloud/configmap-0e4e3fd5": "gardener-apiserver-audit-policy-config-f5b578b4",
+ "reference.resources.gardener.cloud/configmap-1b2d9b42": "gardener-apiserver-audit-policy-config-1e270362",
"reference.resources.gardener.cloud/configmap-6e5f123b": "gardener-apiserver-admission-config-07c5248a",
"reference.resources.gardener.cloud/secret-9dca243c": "shoot-access-gardener-apiserver",
"reference.resources.gardener.cloud/secret-47fc132b": "gardener-apiserver-admission-kubeconfigs-e3b0c442",
@@ -481,7 +481,7 @@ var _ = Describe("GardenerAPIServer", func() {
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
- Name: "gardener-apiserver-audit-policy-config-f5b578b4",
+ Name: "gardener-apiserver-audit-policy-config-1e270362",
},
},
},
@@ -983,8 +983,7 @@ resources:
ObjectMeta: metav1.ObjectMeta{Name: "gardener-apiserver-audit-policy-config", Namespace: namespace},
Data: map[string]string{"audit-policy.yaml": `apiVersion: audit.k8s.io/v1
kind: Policy
-metadata:
- creationTimestamp: null
+metadata: {}
rules:
- level: None
`},
diff --git a/pkg/component/gardener/dashboard/terminal/assets/crd-dashboard.gardener.cloud_terminals.yaml b/pkg/component/gardener/dashboard/terminal/assets/crd-dashboard.gardener.cloud_terminals.yaml
index eb6a403376a..0942283556c 100644
--- a/pkg/component/gardener/dashboard/terminal/assets/crd-dashboard.gardener.cloud_terminals.yaml
+++ b/pkg/component/gardener/dashboard/terminal/assets/crd-dashboard.gardener.cloud_terminals.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
labels:
app.kubernetes.io/component: controller-manager
app.kubernetes.io/name: terminal
@@ -172,7 +172,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
diff --git a/pkg/component/gardener/resourcemanager/assets/crd-resources.gardener.cloud_managedresources.yaml b/pkg/component/gardener/resourcemanager/assets/crd-resources.gardener.cloud_managedresources.yaml
index 2bf40ce0eea..621ec802011 100644
--- a/pkg/component/gardener/resourcemanager/assets/crd-resources.gardener.cloud_managedresources.yaml
+++ b/pkg/component/gardener/resourcemanager/assets/crd-resources.gardener.cloud_managedresources.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: managedresources.resources.gardener.cloud
spec:
group: resources.gardener.cloud
diff --git a/pkg/component/gardener/resourcemanager/resource_manager_test.go b/pkg/component/gardener/resourcemanager/resource_manager_test.go
index 2bb30e98f45..6449c427a86 100644
--- a/pkg/component/gardener/resourcemanager/resource_manager_test.go
+++ b/pkg/component/gardener/resourcemanager/resource_manager_test.go
@@ -1302,7 +1302,6 @@ var _ = Describe("ResourceManager", func() {
out := `apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
- creationTimestamp: null
labels:
app: gardener-resource-manager
name: gardener-resource-manager-shoot
@@ -1579,7 +1578,6 @@ kind: ClusterRoleBinding
metadata:
annotations:
resources.gardener.cloud/keep-object: "true"
- creationTimestamp: null
name: gardener.cloud:target:resource-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
diff --git a/pkg/component/kubernetes/apiserver/apiserver_test.go b/pkg/component/kubernetes/apiserver/apiserver_test.go
index c6932e84929..37a59aff10b 100644
--- a/pkg/component/kubernetes/apiserver/apiserver_test.go
+++ b/pkg/component/kubernetes/apiserver/apiserver_test.go
@@ -109,7 +109,7 @@ var _ = Describe("KubeAPIServer", func() {
configMapNameAdmissionConfigs = "kube-apiserver-admission-config-07c5248a"
secretNameAdmissionKubeconfigs = "kube-apiserver-admission-kubeconfigs-e3b0c442"
secretNameETCDEncryptionConfig = "kube-apiserver-etcd-encryption-configuration-b2b49c90"
- configMapNameAuditPolicy = "audit-policy-config-f5b578b4"
+ configMapNameAuditPolicy = "audit-policy-config-1e270362"
configMapNameEgressPolicy = "kube-apiserver-egress-selector-config-53d92abc"
configMapEnvoyConfig = "kube-apiserver-envoy-config-a60282c1"
configMapEgressSelectorConfig = "kube-apiserver-egress-selector-config-02bc784a"
@@ -1682,8 +1682,7 @@ kubeConfigFile: /etc/kubernetes/admission-kubeconfigs/validatingadmissionwebhook
ObjectMeta: metav1.ObjectMeta{Name: "audit-policy-config", Namespace: namespace},
Data: map[string]string{"audit-policy.yaml": `apiVersion: audit.k8s.io/v1
kind: Policy
-metadata:
- creationTimestamp: null
+metadata: {}
rules:
- level: None
`},
@@ -2764,7 +2763,7 @@ kind: AuthorizationConfiguration
"reference.resources.gardener.cloud/secret-c4700ce9": secretNameETCDEncryptionConfig,
"reference.resources.gardener.cloud/configmap-0ddefe9e": configMapNameAdmissionConfigs,
"reference.resources.gardener.cloud/secret-5613e39f": secretNameAdmissionKubeconfigs,
- "reference.resources.gardener.cloud/configmap-d4419cd4": configMapNameAuditPolicy,
+ "reference.resources.gardener.cloud/configmap-cc790102": configMapNameAuditPolicy,
}
})
@@ -2986,7 +2985,7 @@ kind: AuthorizationConfiguration
"reference.resources.gardener.cloud/secret-c4700ce9": secretNameETCDEncryptionConfig,
"reference.resources.gardener.cloud/configmap-0ddefe9e": configMapNameAdmissionConfigs,
"reference.resources.gardener.cloud/secret-5613e39f": secretNameAdmissionKubeconfigs,
- "reference.resources.gardener.cloud/configmap-d4419cd4": configMapNameAuditPolicy,
+ "reference.resources.gardener.cloud/configmap-cc790102": configMapNameAuditPolicy,
}
})
diff --git a/pkg/component/networking/coredns/coredns_test.go b/pkg/component/networking/coredns/coredns_test.go
index 7527e5a1314..967e59a665d 100644
--- a/pkg/component/networking/coredns/coredns_test.go
+++ b/pkg/component/networking/coredns/coredns_test.go
@@ -65,14 +65,12 @@ var _ = Describe("CoreDNS", func() {
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
name: coredns
namespace: kube-system
`
clusterRoleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
name: system:coredns
rules:
- apiGroups:
@@ -104,7 +102,6 @@ kind: ClusterRoleBinding
metadata:
annotations:
resources.gardener.cloud/delete-on-invalid-update: "true"
- creationTimestamp: null
name: system:coredns
roleRef:
apiGroup: rbac.authorization.k8s.io
@@ -158,7 +155,6 @@ data:
import custom/*.server
kind: ConfigMap
metadata:
- creationTimestamp: null
name: coredns
namespace: kube-system
`
@@ -172,7 +168,6 @@ kind: ConfigMap
metadata:
annotations:
resources.gardener.cloud/ignore: "true"
- creationTimestamp: null
name: coredns-custom
namespace: kube-system
`
@@ -180,7 +175,6 @@ metadata:
out := `apiVersion: v1
kind: Service
metadata:
- creationTimestamp: null
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
@@ -217,7 +211,6 @@ kind: NetworkPolicy
metadata:
annotations:
gardener.cloud/description: Allows CoreDNS to lookup DNS records, talk to the API Server. Also allows CoreDNS to be reachable via its service and its metrics endpoint.
- creationTimestamp: null
name: gardener.cloud--allow-dns
namespace: kube-system
spec:
@@ -262,7 +255,6 @@ spec:
out := `apiVersion: apps/v1
kind: Deployment
metadata:
- creationTimestamp: null
labels:
gardener.cloud/role: system-component
`
@@ -304,8 +296,7 @@ spec:
`
}
- out += ` creationTimestamp: null
- labels:
+ out += ` labels:
gardener.cloud/role: system-component
k8s-app: kube-dns
origin: gardener
@@ -406,7 +397,6 @@ status: {}
pdbYAML = `apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
- creationTimestamp: null
labels:
k8s-app: kube-dns
name: coredns
@@ -427,7 +417,6 @@ status:
hpaYAML = `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
- creationTimestamp: null
labels:
high-availability-config.resources.gardener.cloud/type: server
name: coredns
@@ -455,14 +444,12 @@ status:
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
name: coredns-autoscaler
namespace: kube-system
`
cpacrYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
name: system:coredns-autoscaler
rules:
- apiGroups:
@@ -498,7 +485,6 @@ rules:
cpacrbYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
- creationTimestamp: null
name: system:coredns-autoscaler
roleRef:
apiGroup: rbac.authorization.k8s.io
@@ -512,7 +498,6 @@ subjects:
cpaDeploymentYAML = `apiVersion: apps/v1
kind: Deployment
metadata:
- creationTimestamp: null
labels:
gardener.cloud/role: system-component
k8s-app: coredns-autoscaler
@@ -527,7 +512,6 @@ spec:
strategy: {}
template:
metadata:
- creationTimestamp: null
labels:
gardener.cloud/role: system-component
k8s-app: coredns-autoscaler
@@ -574,7 +558,6 @@ status: {}
cpaDeploymentVpaYAML = `apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
- creationTimestamp: null
name: coredns-autoscaler
namespace: kube-system
spec:
diff --git a/pkg/component/networking/istio/test_charts/ingress_namespace.yaml b/pkg/component/networking/istio/test_charts/ingress_namespace.yaml
index 7e5ce02eded..853090161ca 100644
--- a/pkg/component/networking/istio/test_charts/ingress_namespace.yaml
+++ b/pkg/component/networking/istio/test_charts/ingress_namespace.yaml
@@ -3,7 +3,6 @@ kind: Namespace
metadata:
annotations:
high-availability-config.resources.gardener.cloud/zones: a,b,c
- creationTimestamp: null
labels:
gardener.cloud/role: istio-ingress
high-availability-config.resources.gardener.cloud/consider: "true"
diff --git a/pkg/component/networking/istio/test_charts/ingress_servicemonitor.yaml b/pkg/component/networking/istio/test_charts/ingress_servicemonitor.yaml
index 90ca571028a..c0d4121f95f 100644
--- a/pkg/component/networking/istio/test_charts/ingress_servicemonitor.yaml
+++ b/pkg/component/networking/istio/test_charts/ingress_servicemonitor.yaml
@@ -1,7 +1,6 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
- creationTimestamp: null
labels:
prometheus: aggregate
name: aggregate-istio-ingressgateway
diff --git a/pkg/component/networking/istio/test_charts/ingress_telemetry.yaml b/pkg/component/networking/istio/test_charts/ingress_telemetry.yaml
index 2850e2d4de6..ba9ea10173e 100644
--- a/pkg/component/networking/istio/test_charts/ingress_telemetry.yaml
+++ b/pkg/component/networking/istio/test_charts/ingress_telemetry.yaml
@@ -1,7 +1,6 @@
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
- creationTimestamp: null
labels:
prometheus: aggregate
name: aggregate-enable-upstream-address
diff --git a/pkg/component/networking/istio/test_charts/istiod_servicemonitor.yaml b/pkg/component/networking/istio/test_charts/istiod_servicemonitor.yaml
index beaad08ed45..546eb495d85 100644
--- a/pkg/component/networking/istio/test_charts/istiod_servicemonitor.yaml
+++ b/pkg/component/networking/istio/test_charts/istiod_servicemonitor.yaml
@@ -1,7 +1,6 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
- creationTimestamp: null
labels:
prometheus: aggregate
name: aggregate-istiod
diff --git a/pkg/component/networking/nginxingress/nginxingress_test.go b/pkg/component/networking/nginxingress/nginxingress_test.go
index fa8e98cec75..038ed3337ad 100644
--- a/pkg/component/networking/nginxingress/nginxingress_test.go
+++ b/pkg/component/networking/nginxingress/nginxingress_test.go
@@ -114,7 +114,6 @@ data:
immutable: true
kind: ConfigMap
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -128,7 +127,6 @@ metadata:
clusterRoleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
name: gardener.cloud:seed:nginx-ingress
@@ -207,7 +205,6 @@ rules:
clusterRoleBindingYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
name: gardener.cloud:seed:nginx-ingress
@@ -223,7 +220,6 @@ subjects:
roleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
name: gardener.cloud:seed:nginx-ingress:role
@@ -273,7 +269,6 @@ rules:
roleBindingYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
name: gardener.cloud:seed:nginx-ingress:role-binding
@@ -294,7 +289,6 @@ metadata:
networking.istio.io/exportTo: '*'
networking.resources.gardener.cloud/namespace-selectors: '[{"matchLabels":{"gardener.cloud/role":"istio-ingress"}}]'
some: value
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -320,7 +314,6 @@ status:
serviceBackendYAML = `apiVersion: v1
kind: Service
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: nginx-ingress-k8s-backend
@@ -341,7 +334,6 @@ status:
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
name: nginx-ingress
@@ -350,7 +342,6 @@ metadata:
ingressClassYAML = `apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -361,7 +352,6 @@ spec:
podDisruptionBudgetYAML = `apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -383,7 +373,6 @@ status:
vpaYAML = `apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
- creationTimestamp: null
name: nginx-ingress-controller
namespace: ` + namespace + `
spec:
@@ -403,7 +392,6 @@ status: {}
deploymentBackendYAML = `apiVersion: apps/v1
kind: Deployment
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: nginx-ingress-k8s-backend
@@ -420,7 +408,6 @@ spec:
strategy: {}
template:
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: nginx-ingress-k8s-backend
@@ -462,7 +449,6 @@ kind: Deployment
metadata:
annotations:
` + references.AnnotationKey(references.KindConfigMap, configMapName) + `: ` + configMapName + `
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -481,7 +467,6 @@ spec:
metadata:
annotations:
` + references.AnnotationKey(references.KindConfigMap, configMapName) + `: ` + configMapName + `
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -572,7 +557,6 @@ status: {}
destinationRuleYAML = `apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -602,7 +586,6 @@ status: {}
gatewayYAML = `apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -627,7 +610,6 @@ status: {}
return `apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -659,7 +641,6 @@ kind: Lease
metadata:
annotations:
resources.gardener.cloud/ignore: "true"
- creationTimestamp: null
name: ingress-controller-seed-leader
namespace: ` + namespace + `
spec: {}
@@ -754,7 +735,6 @@ data:
foo: bar
kind: ConfigMap
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -766,7 +746,6 @@ metadata:
ingressClassYAML = `apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -782,7 +761,6 @@ spec:
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
release: addons
@@ -795,7 +773,6 @@ kind: NetworkPolicy
metadata:
annotations:
gardener.cloud/description: Allows all egress and ingress traffic for the nginx-ingress controller.
- creationTimestamp: null
labels:
origin: gardener
name: gardener.cloud--allow-to-from-nginx
@@ -818,7 +795,6 @@ spec:
serviceBackendYAML = `apiVersion: v1
kind: Service
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: nginx-ingress-k8s-backend
@@ -841,7 +817,6 @@ status:
clusterRoleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
release: addons
@@ -924,7 +899,6 @@ kind: ClusterRoleBinding
metadata:
annotations:
resources.gardener.cloud/delete-on-invalid-update: "true"
- creationTimestamp: null
labels:
app: nginx-ingress
release: addons
@@ -944,7 +918,6 @@ kind: Service
metadata:
annotations:
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*'
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -975,7 +948,6 @@ status:
deploymentBackendYAML = `apiVersion: apps/v1
kind: Deployment
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: nginx-ingress-k8s-backend
@@ -995,7 +967,6 @@ spec:
strategy: {}
template:
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: nginx-ingress-k8s-backend
@@ -1044,7 +1015,6 @@ status: {}
out := `apiVersion: apps/v1
kind: Deployment
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -1066,7 +1036,6 @@ spec:
metadata:
annotations:
checksum/config: ` + utils.ComputeChecksum(configMapData) + `
- creationTimestamp: null
labels:
app: nginx-ingress
component: controller
@@ -1162,7 +1131,6 @@ status: {}
roleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
- creationTimestamp: null
labels:
app: nginx-ingress
release: addons
@@ -1216,7 +1184,6 @@ kind: RoleBinding
metadata:
annotations:
resources.gardener.cloud/delete-on-invalid-update: "true"
- creationTimestamp: null
labels:
app: nginx-ingress
release: addons
@@ -1235,7 +1202,6 @@ subjects:
vpaYAML = `apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
- creationTimestamp: null
name: addons-nginx-ingress-controller
namespace: kube-system
spec:
@@ -1258,7 +1224,6 @@ kind: Lease
metadata:
annotations:
resources.gardener.cloud/ignore: "true"
- creationTimestamp: null
name: ingress-controller-leader
namespace: kube-system
spec: {}
diff --git a/pkg/component/networking/nodelocaldns/nodelocaldns_test.go b/pkg/component/networking/nodelocaldns/nodelocaldns_test.go
index 7c4af444a8e..2a0ff6eeed3 100644
--- a/pkg/component/networking/nodelocaldns/nodelocaldns_test.go
+++ b/pkg/component/networking/nodelocaldns/nodelocaldns_test.go
@@ -35,7 +35,6 @@ import (
. "github.com/gardener/gardener/pkg/component/networking/nodelocaldns"
"github.com/gardener/gardener/pkg/resourcemanager/controller/garbagecollector/references"
"github.com/gardener/gardener/pkg/utils"
- kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
"github.com/gardener/gardener/pkg/utils/managedresources"
"github.com/gardener/gardener/pkg/utils/retry"
retryfake "github.com/gardener/gardener/pkg/utils/retry/fake"
@@ -270,17 +269,12 @@ var _ = Describe("NodeLocalDNS", func() {
},
},
}
- shootYAML, err := kubernetesutils.Serialize(shoot, kubernetes.GardenScheme)
- Expect(err).NotTo(HaveOccurred())
- Expect(shootYAML).ToNot(BeEmpty())
-
cluster = &extensionsv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
},
Spec: extensionsv1alpha1.ClusterSpec{
Shoot: runtime.RawExtension{
- Raw: []byte(shootYAML),
Object: shoot,
},
Seed: runtime.RawExtension{
@@ -299,7 +293,6 @@ var _ = Describe("NodeLocalDNS", func() {
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
name: node-local-dns
namespace: kube-system
`
@@ -362,7 +355,6 @@ data:
immutable: true
kind: ConfigMap
metadata:
- creationTimestamp: null
labels:
k8s-app: node-local-dns
resources.gardener.cloud/garbage-collectable-reference: "true"
@@ -376,7 +368,6 @@ metadata:
serviceYAML = `apiVersion: v1
kind: Service
metadata:
- creationTimestamp: null
labels:
k8s-app: kube-dns-upstream
name: kube-dns-upstream
@@ -650,7 +641,6 @@ status:
vpaYAML = `apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
- creationTimestamp: null
name: node-local-dns-worker-aaaa
namespace: kube-system
spec:
diff --git a/pkg/component/nodemanagement/dependencywatchdog/access_test.go b/pkg/component/nodemanagement/dependencywatchdog/access_test.go
index 29bcb819efc..121391a7726 100644
--- a/pkg/component/nodemanagement/dependencywatchdog/access_test.go
+++ b/pkg/component/nodemanagement/dependencywatchdog/access_test.go
@@ -45,7 +45,6 @@ var _ = Describe("Access", func() {
roleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
- creationTimestamp: null
name: gardener.cloud:target:dependency-watchdog
namespace: kube-node-lease
rules:
@@ -61,7 +60,6 @@ rules:
roleBindingYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
- creationTimestamp: null
name: gardener.cloud:target:dependency-watchdog
namespace: kube-node-lease
roleRef:
@@ -77,7 +75,6 @@ subjects:
clusterRoleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
name: gardener.cloud:target:dependency-watchdog
rules:
- apiGroups:
@@ -92,7 +89,6 @@ rules:
clusterRoleBindingYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
- creationTimestamp: null
name: gardener.cloud:target:dependency-watchdog
roleRef:
apiGroup: rbac.authorization.k8s.io
@@ -143,7 +139,6 @@ contexts:
name: ` + namespace + `
current-context: ` + namespace + `
kind: Config
-preferences: {}
users:
- name: ` + namespace + `
user: {}
@@ -155,13 +150,13 @@ users:
Name: "shoot-core-dependency-watchdog",
Namespace: namespace,
Labels: map[string]string{"origin": "gardener"},
- Annotations: map[string]string{"reference.resources.gardener.cloud/secret-dd60c006": "managedresource-shoot-core-dependency-watchdog-412f1efe"},
+ Annotations: map[string]string{"reference.resources.gardener.cloud/secret-e3a35806": "managedresource-shoot-core-dependency-watchdog-3cb55785"},
ResourceVersion: "1",
},
Spec: resourcesv1alpha1.ManagedResourceSpec{
SecretRefs: []corev1.LocalObjectReference{
{
- Name: "managedresource-shoot-core-dependency-watchdog-412f1efe",
+ Name: "managedresource-shoot-core-dependency-watchdog-3cb55785",
},
},
InjectLabels: map[string]string{"shoot.gardener.cloud/no-cleanup": "true"},
@@ -170,7 +165,7 @@ users:
}
expectedManagedResourceSecret = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
- Name: "managedresource-shoot-core-dependency-watchdog-412f1efe",
+ Name: "managedresource-shoot-core-dependency-watchdog-3cb55785",
Namespace: namespace,
Labels: map[string]string{
"resources.gardener.cloud/garbage-collectable-reference": "true",
@@ -197,7 +192,7 @@ users:
Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(reconciledManagedResource), reconciledManagedResource)).To(Succeed())
Expect(reconciledManagedResource).To(DeepEqual(expectedManagedResource))
- reconciledManagedResourceSecret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "managedresource-shoot-core-dependency-watchdog-412f1efe", Namespace: namespace}}
+ reconciledManagedResourceSecret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "managedresource-shoot-core-dependency-watchdog-3cb55785", Namespace: namespace}}
Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(reconciledManagedResourceSecret), reconciledManagedResourceSecret)).To(Succeed())
Expect(reconciledManagedResourceSecret.Type).To(Equal(corev1.SecretTypeOpaque))
Expect(reconciledManagedResourceSecret.Immutable).To(Equal(ptr.To(true)))
diff --git a/pkg/component/nodemanagement/dependencywatchdog/bootstrap_test.go b/pkg/component/nodemanagement/dependencywatchdog/bootstrap_test.go
index 15e5a9d0efb..92f1e4ffca1 100644
--- a/pkg/component/nodemanagement/dependencywatchdog/bootstrap_test.go
+++ b/pkg/component/nodemanagement/dependencywatchdog/bootstrap_test.go
@@ -59,7 +59,6 @@ var _ = Describe("DependencyWatchdog", func() {
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
name: ` + dwdName + `
namespace: ` + namespace + `
`
@@ -68,7 +67,6 @@ metadata:
out := `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
name: gardener.cloud:` + dwdName + `
rules:`
if role == RoleWeeder {
@@ -140,7 +138,6 @@ rules:`
clusterRoleBindingYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
- creationTimestamp: null
name: gardener.cloud:` + dwdName + `
roleRef:
apiGroup: rbac.authorization.k8s.io
@@ -156,7 +153,6 @@ subjects:
out := `apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
- creationTimestamp: null
name: gardener.cloud:` + dwdName + `
namespace: ` + namespace + `
rules:`
@@ -225,7 +221,6 @@ rules:`
roleBindingYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
- creationTimestamp: null
name: gardener.cloud:` + dwdName + `
namespace: ` + namespace + `
roleRef:
@@ -259,7 +254,6 @@ data:
out += `immutable: true
kind: ConfigMap
metadata:
- creationTimestamp: null
labels:
app: ` + dwdName + `
resources.gardener.cloud/garbage-collectable-reference: "true"
@@ -276,7 +270,6 @@ kind: Deployment
metadata:
annotations:
` + references.AnnotationKey(references.KindConfigMap, configMapName) + `: ` + configMapName + `
- creationTimestamp: null
labels:
app: ` + dwdName + `
high-availability-config.resources.gardener.cloud/type: controller
@@ -293,7 +286,6 @@ spec:
metadata:
annotations:
` + references.AnnotationKey(references.KindConfigMap, configMapName) + `: ` + configMapName + `
- creationTimestamp: null
labels:
app: ` + dwdName
@@ -375,7 +367,6 @@ status: {}
out := `apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
- creationTimestamp: null
name: ` + dwdName + `
namespace: ` + namespace + `
spec:
@@ -409,7 +400,6 @@ status: {}
podDisruptionYAML = `apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
- creationTimestamp: null
labels:
app: ` + dwdName + `
name: ` + dwdName + `
diff --git a/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager_test.go b/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager_test.go
index acbfe7041be..54eb7789f81 100644
--- a/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager_test.go
+++ b/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager_test.go
@@ -406,7 +406,6 @@ var _ = Describe("MachineControllerManager", func() {
clusterRoleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
name: gardener.cloud:target:machine-controller-manager
rules:
- apiGroups:
@@ -485,7 +484,6 @@ rules:
clusterRoleBindingYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
- creationTimestamp: null
name: gardener.cloud:target:machine-controller-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
@@ -500,7 +498,6 @@ subjects:
roleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
- creationTimestamp: null
name: gardener.cloud:target:machine-controller-manager
namespace: kube-system
rules:
@@ -518,7 +515,6 @@ rules:
roleBindingYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
- creationTimestamp: null
name: gardener.cloud:target:machine-controller-manager
namespace: kube-system
roleRef:
diff --git a/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml b/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml
index 925b4e4a82b..7329a338f25 100644
--- a/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml
+++ b/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: machineclasses.machine.sapcloud.io
spec:
group: machine.sapcloud.io
diff --git a/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml b/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml
index 00bcea01a56..450e8bf6284 100644
--- a/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml
+++ b/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: machinedeployments.machine.sapcloud.io
spec:
group: machine.sapcloud.io
@@ -399,9 +399,8 @@ spec:
to a node.
type: string
timeAdded:
- description: |-
- TimeAdded represents the time at which the taint was added.
- It is only written for NoExecute taints.
+ description: TimeAdded represents the time at
+ which the taint was added.
format: date-time
type: string
value:
diff --git a/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machines.yaml b/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machines.yaml
index f0c7c59bacc..7983b7f29f9 100644
--- a/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machines.yaml
+++ b/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machines.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: machines.machine.sapcloud.io
spec:
group: machine.sapcloud.io
@@ -196,9 +196,8 @@ spec:
a node.
type: string
timeAdded:
- description: |-
- TimeAdded represents the time at which the taint was added.
- It is only written for NoExecute taints.
+ description: TimeAdded represents the time at which
+ the taint was added.
format: date-time
type: string
value:
diff --git a/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinesets.yaml b/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinesets.yaml
index 5512b600e36..d9933286359 100644
--- a/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinesets.yaml
+++ b/pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinesets.yaml
@@ -5,7 +5,7 @@ metadata:
labels:
gardener.cloud/deletion-protected: "true"
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: machinesets.machine.sapcloud.io
spec:
group: machine.sapcloud.io
@@ -281,9 +281,8 @@ spec:
to a node.
type: string
timeAdded:
- description: |-
- TimeAdded represents the time at which the taint was added.
- It is only written for NoExecute taints.
+ description: TimeAdded represents the time at
+ which the taint was added.
format: date-time
type: string
value:
diff --git a/pkg/component/nodemanagement/nodeproblemdetector/node_problem_detector_test.go b/pkg/component/nodemanagement/nodeproblemdetector/node_problem_detector_test.go
index a1824680326..11cb780a7bd 100644
--- a/pkg/component/nodemanagement/nodeproblemdetector/node_problem_detector_test.go
+++ b/pkg/component/nodemanagement/nodeproblemdetector/node_problem_detector_test.go
@@ -78,7 +78,6 @@ var _ = Describe("NodeProblemDetector", func() {
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
labels:
app.kubernetes.io/instance: shoot-core
app.kubernetes.io/name: node-problem-detector
@@ -88,7 +87,6 @@ metadata:
clusterRoleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
labels:
app.kubernetes.io/instance: shoot-core
app.kubernetes.io/name: node-problem-detector
@@ -120,7 +118,6 @@ kind: ClusterRoleBinding
metadata:
annotations:
resources.gardener.cloud/delete-on-invalid-update: "true"
- creationTimestamp: null
labels:
app.kubernetes.io/instance: shoot-core
app.kubernetes.io/name: node-problem-detector
@@ -138,7 +135,6 @@ subjects:
serviceYAML = `apiVersion: v1
kind: Service
metadata:
- creationTimestamp: null
labels:
app: node-problem-detector
app.kubernetes.io/instance: shoot-core
@@ -163,7 +159,6 @@ status:
out := `apiVersion: apps/v1
kind: DaemonSet
metadata:
- creationTimestamp: null
labels:
app.kubernetes.io/instance: shoot-core
app.kubernetes.io/name: node-problem-detector
@@ -180,7 +175,6 @@ spec:
app.kubernetes.io/name: node-problem-detector
template:
metadata:
- creationTimestamp: null
labels:
app: node-problem-detector
app.kubernetes.io/instance: shoot-core
@@ -265,7 +259,6 @@ status:
vpaYAML = `apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
- creationTimestamp: null
name: node-problem-detector
namespace: kube-system
spec:
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfilters.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfilters.yaml
index a5789bad004..624039566a0 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfilters.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfilters.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusterfilters.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
index 8506b8bcccc..2aaeb309652 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusterfluentbitconfigs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterinputs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterinputs.yaml
index 7931598ceb0..f3813ba4343 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterinputs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterinputs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusterinputs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clustermultilineparsers.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clustermultilineparsers.yaml
index e6fe12dea7d..e56ff886a2d 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clustermultilineparsers.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clustermultilineparsers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clustermultilineparsers.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusteroutputs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusteroutputs.yaml
index 79e5b28708d..f53fd251fb4 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusteroutputs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusteroutputs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusteroutputs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterparsers.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterparsers.yaml
index e36b427f0b9..0e2983036e5 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterparsers.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterparsers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: clusterparsers.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_collectors.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_collectors.yaml
index 0f7bc38be2f..c99f8c00ad4 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_collectors.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_collectors.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: collectors.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
@@ -610,8 +610,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -1252,15 +1252,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -1420,13 +1418,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -1514,7 +1510,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2545,15 +2541,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -2735,12 +2729,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -2819,7 +2811,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -3239,6 +3231,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -3373,7 +3470,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_filters.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_filters.yaml
index fcb3d3d56c4..55135835718 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_filters.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_filters.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: filters.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbitconfigs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbitconfigs.yaml
index 55ec28f4b8d..aafe67c640f 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbitconfigs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbitconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: fluentbitconfigs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbits.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbits.yaml
index 506efe9bfa1..99e95fff5a2 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbits.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbits.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: fluentbits.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
@@ -610,8 +610,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -1183,7 +1183,9 @@ spec:
a Container.
properties:
name:
- description: Name of the environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1241,6 +1243,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1391,8 +1430,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1450,6 +1490,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1510,8 +1587,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -1538,8 +1615,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -2210,7 +2288,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2264,10 +2342,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -2279,6 +2357,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -3707,15 +3838,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -3896,12 +4025,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details Glusterfs
+ topology.
type: string
path:
description: |-
@@ -3980,7 +4107,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -4392,6 +4519,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be addressed
+ to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -4526,7 +4758,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
@@ -5019,7 +5250,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6055,15 +6286,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -6245,12 +6474,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -6329,7 +6556,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -6749,6 +6976,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -6883,7 +7215,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_multilineparsers.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_multilineparsers.yaml
index ec684d1414c..be64ff720a4 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_multilineparsers.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_multilineparsers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: multilineparsers.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_outputs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_outputs.yaml
index 830a88f558e..7da1e0b4203 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_outputs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_outputs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: outputs.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_parsers.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_parsers.yaml
index 9d6c5136586..6bfe5e95284 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_parsers.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_parsers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: parsers.fluentbit.fluent.io
spec:
group: fluentbit.fluent.io
diff --git a/pkg/component/observability/monitoring/blackboxexporter/blackboxexporter_test.go b/pkg/component/observability/monitoring/blackboxexporter/blackboxexporter_test.go
index 04ea3e23c31..2a72a3bfc03 100644
--- a/pkg/component/observability/monitoring/blackboxexporter/blackboxexporter_test.go
+++ b/pkg/component/observability/monitoring/blackboxexporter/blackboxexporter_test.go
@@ -117,7 +117,6 @@ var _ = Describe("BlackboxExporter", func() {
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
labels:
app: blackbox-exporter
gardener.cloud/role: monitoring
@@ -134,7 +133,6 @@ data:
immutable: true
kind: ConfigMap
metadata:
- creationTimestamp: null
labels:
app: prometheus
resources.gardener.cloud/garbage-collectable-reference: "true"
@@ -146,7 +144,6 @@ metadata:
pdbYAML = `apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
- creationTimestamp: null
labels:
app: blackbox-exporter
gardener.cloud/role: monitoring
@@ -171,7 +168,6 @@ kind: Deployment
metadata:
annotations:
` + references.AnnotationKey(references.KindConfigMap, configMapName) + `: ` + configMapName + `
- creationTimestamp: null
labels:
app: blackbox-exporter
gardener.cloud/role: monitoring
@@ -190,7 +186,6 @@ spec:
metadata:
annotations:
` + references.AnnotationKey(references.KindConfigMap, configMapName) + `: ` + configMapName + `
- creationTimestamp: null
labels:
app: blackbox-exporter
bar: foo
@@ -309,7 +304,6 @@ metadata:`
}
out += `
- creationTimestamp: null
labels:
app: blackbox-exporter
name: blackbox-exporter
@@ -332,7 +326,6 @@ status:
vpaYAML = `apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
- creationTimestamp: null
name: blackbox-exporter
namespace: ` + resourcesNamespace + `
spec:
@@ -438,7 +431,6 @@ status: {}
scrapeConfigYAML = `apiVersion: monitoring.coreos.com/v1alpha1
kind: ScrapeConfig
metadata:
- creationTimestamp: null
name: foo
namespace: ` + namespace + `
spec: {}
@@ -447,7 +439,6 @@ spec: {}
prometheusRuleYAML = `apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
- creationTimestamp: null
name: bar
namespace: ` + namespace + `
spec: {}
diff --git a/pkg/component/observability/monitoring/metricsserver/metricsserver_test.go b/pkg/component/observability/monitoring/metricsserver/metricsserver_test.go
index 1cc5642f24c..e8e0d0f7178 100644
--- a/pkg/component/observability/monitoring/metricsserver/metricsserver_test.go
+++ b/pkg/component/observability/monitoring/metricsserver/metricsserver_test.go
@@ -44,7 +44,6 @@ var _ = Describe("MetricsServer", func() {
serviceYAML = `apiVersion: v1
kind: Service
metadata:
- creationTimestamp: null
labels:
kubernetes.io/name: metrics-server
name: metrics-server
@@ -62,7 +61,6 @@ status:
apiServiceYAML = `apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
- creationTimestamp: null
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
@@ -77,7 +75,6 @@ status: {}
vpaYAML = `apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
- creationTimestamp: null
name: metrics-server
namespace: kube-system
spec:
@@ -98,7 +95,6 @@ status: {}
clusterRoleYAML = `apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
name: system:metrics-server
rules:
- apiGroups:
@@ -119,7 +115,6 @@ kind: ClusterRoleBinding
metadata:
annotations:
resources.gardener.cloud/delete-on-invalid-update: "true"
- creationTimestamp: null
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
@@ -135,7 +130,6 @@ kind: ClusterRoleBinding
metadata:
annotations:
resources.gardener.cloud/delete-on-invalid-update: "true"
- creationTimestamp: null
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
@@ -151,7 +145,6 @@ kind: RoleBinding
metadata:
annotations:
resources.gardener.cloud/delete-on-invalid-update: "true"
- creationTimestamp: null
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
@@ -167,7 +160,6 @@ subjects:
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
name: metrics-server
namespace: kube-system
`
@@ -183,7 +175,6 @@ kind: Deployment
metadata:
annotations:
` + references.AnnotationKey(references.KindSecret, secretName) + `: ` + secretName + `
- creationTimestamp: null
labels:
gardener.cloud/role: system-component
high-availability-config.resources.gardener.cloud/type: server
@@ -204,7 +195,6 @@ spec:
metadata:
annotations:
` + references.AnnotationKey(references.KindSecret, secretName) + `: ` + secretName + `
- creationTimestamp: null
labels:
gardener.cloud/role: system-component
k8s-app: metrics-server
@@ -288,7 +278,6 @@ status: {}
pdbYAML = `apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
- creationTimestamp: null
labels:
k8s-app: metrics-server
name: metrics-server
diff --git a/pkg/component/observability/monitoring/nodeexporter/nodeexporter_test.go b/pkg/component/observability/monitoring/nodeexporter/nodeexporter_test.go
index e6dec3899b1..681ab09f530 100644
--- a/pkg/component/observability/monitoring/nodeexporter/nodeexporter_test.go
+++ b/pkg/component/observability/monitoring/nodeexporter/nodeexporter_test.go
@@ -270,7 +270,6 @@ var _ = Describe("NodeExporter", func() {
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
- creationTimestamp: null
labels:
component: node-exporter
name: node-exporter
@@ -279,7 +278,6 @@ metadata:
serviceYAML = `apiVersion: v1
kind: Service
metadata:
- creationTimestamp: null
labels:
component: node-exporter
name: node-exporter
@@ -300,7 +298,6 @@ status:
daemonSetYAML = `apiVersion: apps/v1
kind: DaemonSet
metadata:
- creationTimestamp: null
labels:
component: node-exporter
gardener.cloud/role: monitoring
@@ -314,7 +311,6 @@ spec:
component: node-exporter
template:
metadata:
- creationTimestamp: null
labels:
component: node-exporter
gardener.cloud/role: monitoring
@@ -411,7 +407,6 @@ status:
vpaYAML = `apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
- creationTimestamp: null
name: node-exporter
namespace: kube-system
spec:
diff --git a/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_perses.yaml b/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_perses.yaml
index 78ded4e5638..3a9e93b42ce 100644
--- a/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_perses.yaml
+++ b/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_perses.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: perses.perses.dev
spec:
group: perses.dev
@@ -610,8 +610,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
diff --git a/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_persesdashboards.yaml b/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_persesdashboards.yaml
index e88d62e47f1..301ea4eb0e6 100644
--- a/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_persesdashboards.yaml
+++ b/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_persesdashboards.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: persesdashboards.perses.dev
spec:
group: perses.dev
diff --git a/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_persesdatasources.yaml b/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_persesdatasources.yaml
index 07c4e8a0fef..4e4838af27b 100644
--- a/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_persesdatasources.yaml
+++ b/pkg/component/observability/monitoring/persesoperator/templates/crd-perses.dev_persesdatasources.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: persesdatasources.perses.dev
spec:
group: perses.dev
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_alertmanagerconfigs.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_alertmanagerconfigs.yaml
index 0298bac64ca..88429306f60 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_alertmanagerconfigs.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_alertmanagerconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: alertmanagerconfigs.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_alertmanagers.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_alertmanagers.yaml
index c1319eb26a8..96fad4d0d5d 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_alertmanagers.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_alertmanagers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: alertmanagers.monitoring.coreos.com
spec:
group: monitoring.coreos.com
@@ -674,8 +674,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -2887,8 +2887,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -2946,6 +2947,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -3006,8 +3044,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -3034,8 +3072,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -3706,7 +3745,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3760,10 +3799,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -3775,6 +3814,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -4476,8 +4568,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -4535,6 +4628,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -4595,8 +4725,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -4623,8 +4753,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -5295,7 +5426,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -5349,10 +5480,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -5364,6 +5495,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -6009,7 +6193,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6597,15 +6781,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -6853,15 +7035,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -7023,13 +7203,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -8034,15 +8212,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -8224,12 +8400,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -8308,7 +8482,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -8728,6 +8902,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -8862,7 +9141,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_podmonitors.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_podmonitors.yaml
index 5aac7b91cce..c888967e7c4 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_podmonitors.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_podmonitors.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: podmonitors.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_probes.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_probes.yaml
index 0cc48a5bab3..4ac47e50aa1 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_probes.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_probes.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: probes.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheusagents.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheusagents.yaml
index 5d17a634635..74e741011b3 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheusagents.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheusagents.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: prometheusagents.monitoring.coreos.com
spec:
group: monitoring.coreos.com
@@ -705,8 +705,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -1510,8 +1510,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1569,6 +1570,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1629,8 +1667,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -1657,8 +1695,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -2329,7 +2368,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2383,10 +2422,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -2398,6 +2437,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -3337,8 +3429,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -3396,6 +3489,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -3456,8 +3586,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -3484,8 +3614,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -4156,7 +4287,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -4210,10 +4341,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -4225,6 +4356,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -6354,7 +6538,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -7736,15 +7920,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -7992,15 +8174,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -8162,13 +8342,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -9432,15 +9610,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -9622,12 +9798,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -9706,7 +9880,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -10126,6 +10300,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -10260,7 +10539,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheuses.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheuses.yaml
index 00768cd7ecc..c5420605b20 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheuses.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheuses.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: prometheuses.monitoring.coreos.com
spec:
group: monitoring.coreos.com
@@ -783,8 +783,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -2248,8 +2248,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -2307,6 +2308,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -2367,8 +2405,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -2395,8 +2433,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -3067,7 +3106,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3121,10 +3160,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -3136,6 +3175,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -4117,8 +4209,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -4176,6 +4269,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -4236,8 +4366,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -4264,8 +4394,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -4936,7 +5067,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -4990,10 +5121,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -5005,6 +5136,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -7920,7 +8104,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -9485,15 +9669,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -9741,15 +9923,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -9911,13 +10091,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -10304,7 +10482,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -11698,15 +11876,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -11888,12 +12064,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -11972,7 +12146,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -12392,6 +12566,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -12526,7 +12805,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheusrules.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheusrules.yaml
index 6e41ee48a8d..f4800ee9ed9 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheusrules.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_prometheusrules.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: prometheusrules.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_scrapeconfigs.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_scrapeconfigs.yaml
index e9157384362..b6a61bb8bad 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_scrapeconfigs.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_scrapeconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: scrapeconfigs.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_servicemonitors.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_servicemonitors.yaml
index 0d868a6074e..5913993c581 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_servicemonitors.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_servicemonitors.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: servicemonitors.monitoring.coreos.com
spec:
group: monitoring.coreos.com
diff --git a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_thanosrulers.yaml b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_thanosrulers.yaml
index be079491bcd..2285730da9d 100644
--- a/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_thanosrulers.yaml
+++ b/pkg/component/observability/monitoring/prometheusoperator/templates/crd-monitoring.coreos.com_thanosrulers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: thanosrulers.monitoring.coreos.com
spec:
group: monitoring.coreos.com
@@ -671,8 +671,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -1165,8 +1165,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1224,6 +1225,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1284,8 +1322,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -1312,8 +1350,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -1984,7 +2023,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2038,10 +2077,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -2053,6 +2092,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -2974,8 +3066,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -3033,6 +3126,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -3093,8 +3223,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -3121,8 +3251,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -3793,7 +3924,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3847,10 +3978,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -3862,6 +3993,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -5680,7 +5864,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6374,15 +6558,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -6630,15 +6812,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -6800,13 +6980,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -7850,15 +8028,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -8040,12 +8216,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -8124,7 +8298,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -8544,6 +8718,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -8678,7 +8957,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_instrumentations.yaml b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_instrumentations.yaml
index 53925b8a724..4ce815cc83d 100644
--- a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_instrumentations.yaml
+++ b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_instrumentations.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: instrumentations.opentelemetry.io
spec:
group: opentelemetry.io
@@ -69,8 +69,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -128,6 +129,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -197,8 +235,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -256,6 +295,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -321,7 +397,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -568,15 +644,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -626,8 +700,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -685,6 +760,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -750,7 +862,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -993,15 +1105,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -1036,7 +1146,9 @@ spec:
a Container.
properties:
name:
- description: Name of the environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1094,6 +1206,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1207,8 +1356,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1266,6 +1416,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1331,7 +1518,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -1574,15 +1761,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -1626,8 +1811,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1685,6 +1871,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1770,7 +1993,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2013,15 +2236,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -2059,8 +2280,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -2118,6 +2340,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -2187,8 +2446,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -2246,6 +2506,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -2311,7 +2608,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2554,15 +2851,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -2600,8 +2895,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -2659,6 +2955,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -2724,7 +3057,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2967,15 +3300,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -3031,8 +3362,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -3090,6 +3422,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -3155,7 +3524,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3398,15 +3767,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
diff --git a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opampbridges.yaml b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opampbridges.yaml
index b05dde2b7c2..0e570643ee7 100644
--- a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opampbridges.yaml
+++ b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opampbridges.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: opampbridges.opentelemetry.io
spec:
group: opentelemetry.io
@@ -619,8 +619,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -999,7 +999,9 @@ spec:
a Container.
properties:
name:
- description: Name of the environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -1057,6 +1059,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -1135,8 +1174,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each environment
- variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -1570,7 +1610,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -2781,15 +2821,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -2971,12 +3009,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -3055,7 +3091,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -3475,6 +3511,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -3609,7 +3750,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opentelemetrycollectors.yaml b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opentelemetrycollectors.yaml
index 96453700115..1e4a435e3ab 100644
--- a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opentelemetrycollectors.yaml
+++ b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opentelemetrycollectors.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: opentelemetrycollectors.opentelemetry.io
spec:
group: opentelemetry.io
@@ -118,8 +118,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -177,6 +178,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -237,8 +275,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -265,8 +303,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -937,7 +976,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -991,10 +1030,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -1006,6 +1045,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -2073,8 +2165,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -2850,7 +2942,7 @@ spec:
pod is available (Ready for at least minReadySeconds) the old DaemonSet pod
on that node is marked deleted. If the old pod becomes unavailable for any
reason (Ready transitions to false, is evicted, or is drained) an updated
- pod is immediatedly created on that node without considering surge limits.
+ pod is immediately created on that node without considering surge limits.
Allowing surge implies the possibility that the resources consumed by the
daemonset on any given node can double if the readiness check fails, and
so resource intensive daemonsets should take into account that they may
@@ -2942,7 +3034,9 @@ spec:
a Container.
properties:
name:
- description: Name of the environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -3000,6 +3094,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -3078,8 +3209,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each environment
- variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -3242,8 +3374,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -3301,6 +3434,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -3361,8 +3531,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -3389,8 +3559,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -4061,7 +4232,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -4115,10 +4286,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -4130,6 +4301,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -5470,7 +5694,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6364,8 +6588,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -6749,8 +6973,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be a
- C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -6808,6 +7033,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -7418,7 +7680,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -8333,15 +8595,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -8504,13 +8764,11 @@ spec:
description: |-
currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using.
When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
type: string
modifyVolumeStatus:
description: |-
ModifyVolumeStatus represents the status object of ControllerModifyVolume operation.
When this is unset, there is no ModifyVolume operation being attempted.
- This is a beta field and requires enabling VolumeAttributesClass feature (off by default).
properties:
status:
description: "status is the status of the ControllerModifyVolume
@@ -9281,15 +9539,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -9471,12 +9727,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -9555,7 +9809,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -9975,6 +10229,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -10109,7 +10468,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_targetallocators.yaml b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_targetallocators.yaml
index 67af03ca807..ef04fe2003e 100644
--- a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_targetallocators.yaml
+++ b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_targetallocators.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: targetallocators.opentelemetry.io
spec:
group: opentelemetry.io
@@ -103,8 +103,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -162,6 +163,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -222,8 +260,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -250,8 +288,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -922,7 +961,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -976,10 +1015,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -991,6 +1030,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -2058,8 +2150,8 @@ spec:
most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource
request, requiredDuringScheduling anti-affinity expressions, etc.),
- compute a sum by iterating through the elements of this field and adding
- "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ compute a sum by iterating through the elements of this field and subtracting
+ "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the
node(s) with the highest sum are the most preferred.
items:
description: The weights of all of the matched WeightedPodAffinityTerm
@@ -2436,7 +2528,9 @@ spec:
a Container.
properties:
name:
- description: Name of the environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -2494,6 +2588,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -2572,8 +2703,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each environment
- variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -2669,8 +2801,9 @@ spec:
in a Container.
properties:
name:
- description: Name of the environment variable. Must be
- a C_IDENTIFIER.
+ description: |-
+ Name of the environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
value:
description: |-
@@ -2728,6 +2861,43 @@ spec:
- fieldPath
type: object
x-kubernetes-map-type: atomic
+ fileKeyRef:
+ description: |-
+ FileKeyRef selects a key of the env file.
+ Requires the EnvFiles feature gate to be enabled.
+ properties:
+ key:
+ description: |-
+ The key within the env file. An invalid key will prevent the pod from starting.
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
+ type: string
+ optional:
+ default: false
+ description: |-
+ Specify whether the file or its key must be defined. If the file or key
+ does not exist, then the env var is not published.
+ If optional is set to true and the specified key does not exist,
+ the environment variable will not be set in the Pod's containers.
+
+ If optional is set to false and the specified key does not exist,
+ an error will be returned during Pod creation.
+ type: boolean
+ path:
+ description: |-
+ The path within the volume from which to select the file.
+ Must be relative and may not contain the '..' path or start with '..'.
+ type: string
+ volumeName:
+ description: The name of the volume mount containing
+ the env file.
+ type: string
+ required:
+ - key
+ - path
+ - volumeName
+ type: object
+ x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
@@ -2788,8 +2958,8 @@ spec:
envFrom:
description: |-
List of sources to populate environment variables in the container.
- The keys defined within a source must be a C_IDENTIFIER. All invalid keys
- will be reported as an event when the container is starting. When a key exists in multiple
+ The keys defined within a source may consist of any printable ASCII characters except '='.
+ When a key exists in multiple
sources, the value associated with the last source will take precedence.
Values defined by an Env with a duplicate key will take precedence.
Cannot be updated.
@@ -2816,8 +2986,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
prefix:
- description: Optional text to prepend to the name of each
- environment variable. Must be a C_IDENTIFIER.
+ description: |-
+ Optional text to prepend to the name of each environment variable.
+ May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
@@ -3488,7 +3659,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -3542,10 +3713,10 @@ spec:
restartPolicy:
description: |-
RestartPolicy defines the restart behavior of individual containers in a pod.
- This field may only be set for init containers, and the only allowed value is "Always".
- For non-init containers or when this field is not specified,
+ This overrides the pod-level restart policy. When this field is not specified,
the restart behavior is defined by the Pod's restart policy and the container type.
- Setting the RestartPolicy as "Always" for the init container will have the following effect:
+ Additionally, setting the RestartPolicy as "Always" for the init container will
+ have the following effect:
this init container will be continually restarted on
exit until all regular containers have terminated. Once all regular
containers have completed, all init containers with restartPolicy "Always"
@@ -3557,6 +3728,59 @@ spec:
init container is started, or after any startupProbe has successfully
completed.
type: string
+ restartPolicyRules:
+ description: |-
+ Represents a list of rules to be checked to determine if the
+ container should be restarted on exit. The rules are evaluated in
+ order. Once a rule matches a container exit condition, the remaining
+ rules are ignored. If no rule matches the container exit condition,
+ the Container-level restart policy determines the whether the container
+ is restarted or not. Constraints on the rules:
+ - At most 20 rules are allowed.
+ - Rules can have the same action.
+ - Identical rules are not forbidden in validations.
+ When rules are specified, container MUST set RestartPolicy explicitly
+ even it if matches the Pod's RestartPolicy.
+ items:
+ description: ContainerRestartRule describes how a container
+ exit is handled.
+ properties:
+ action:
+ description: |-
+ Specifies the action taken on a container exit if the requirements
+ are satisfied. The only possible value is "Restart" to restart the
+ container.
+ type: string
+ exitCodes:
+ description: Represents the exit codes to check on container
+ exits.
+ properties:
+ operator:
+ description: |-
+ Represents the relationship between the container exit code(s) and the
+ specified values. Possible values are:
+ - In: the requirement is satisfied if the container exit code is in the
+ set of specified values.
+ - NotIn: the requirement is satisfied if the container exit code is
+ not in the set of specified values.
+ type: string
+ values:
+ description: |-
+ Specifies the set of values to check for container exit codes.
+ At most 255 elements are allowed.
+ items:
+ format: int32
+ type: integer
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - operator
+ type: object
+ required:
+ - action
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
securityContext:
description: |-
SecurityContext defines the security options the container should be run with.
@@ -4995,7 +5219,7 @@ spec:
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
- This is an alpha field and requires enabling the
+ This field depends on the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
@@ -6236,15 +6460,13 @@ spec:
volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.
If specified, the CSI driver will create or update the volume with the attributes defined
in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName,
- it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass
- will be applied to the claim but it's not allowed to reset this field to empty string once it is set.
- If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass
- will be set by the persistentvolume controller if it exists.
+ it can be changed after the claim is created. An empty string or nil value indicates that no
+ VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state,
+ this field can be reset to its previous value (including nil) to cancel the modification.
If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be
set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource
exists.
More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
- (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default).
type: string
volumeMode:
description: |-
@@ -6426,12 +6648,10 @@ spec:
description: |-
glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime.
Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md
properties:
endpoints:
- description: |-
- endpoints is the endpoint name that details Glusterfs topology.
- More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod
+ description: endpoints is the endpoint name that details
+ Glusterfs topology.
type: string
path:
description: |-
@@ -6510,7 +6730,7 @@ spec:
description: |-
iscsi represents an ISCSI Disk resource that is attached to a
kubelet's host machine and then exposed to the pod.
- More info: https://examples.k8s.io/volumes/iscsi/README.md
+ More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi
properties:
chapAuthDiscovery:
description: chapAuthDiscovery defines whether support iSCSI
@@ -6930,6 +7150,111 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ podCertificate:
+ description: |-
+ Projects an auto-rotating credential bundle (private key and certificate
+ chain) that the pod can use either as a TLS client or server.
+
+ Kubelet generates a private key and uses it to send a
+ PodCertificateRequest to the named signer. Once the signer approves the
+ request and issues a certificate chain, Kubelet writes the key and
+ certificate chain to the pod filesystem. The pod does not start until
+ certificates have been issued for each podCertificate projected volume
+ source in its spec.
+
+ Kubelet will begin trying to rotate the certificate at the time indicated
+ by the signer using the PodCertificateRequest.Status.BeginRefreshAt
+ timestamp.
+
+ Kubelet can write a single file, indicated by the credentialBundlePath
+ field, or separate files, indicated by the keyPath and
+ certificateChainPath fields.
+
+ The credential bundle is a single file in PEM format. The first PEM
+ entry is the private key (in PKCS#8 format), and the remaining PEM
+ entries are the certificate chain issued by the signer (typically,
+ signers will return their certificate chain in leaf-to-root order).
+
+ Prefer using the credential bundle format, since your application code
+ can read it atomically. If you use keyPath and certificateChainPath,
+ your application must make two separate file reads. If these coincide
+ with a certificate rotation, it is possible that the private key and leaf
+ certificate you read may not correspond to each other. Your application
+ will need to check for this condition, and re-read until they are
+ consistent.
+
+ The named signer controls chooses the format of the certificate it
+ issues; consult the signer implementation's documentation to learn how to
+ use the certificates it issues.
+ properties:
+ certificateChainPath:
+ description: |-
+ Write the certificate chain at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ credentialBundlePath:
+ description: |-
+ Write the credential bundle at this path in the projected volume.
+
+ The credential bundle is a single file that contains multiple PEM blocks.
+ The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private
+ key.
+
+ The remaining blocks are CERTIFICATE blocks, containing the issued
+ certificate chain from the signer (leaf and any intermediates).
+
+ Using credentialBundlePath lets your Pod's application code make a single
+ atomic read that retrieves a consistent key and certificate chain. If you
+ project them to separate files, your application code will need to
+ additionally check that the leaf certificate was issued to the key.
+ type: string
+ keyPath:
+ description: |-
+ Write the key at this path in the projected volume.
+
+ Most applications should use credentialBundlePath. When using keyPath
+ and certificateChainPath, your application needs to check that the key
+ and leaf certificate are consistent, because it is possible to read the
+ files mid-rotation.
+ type: string
+ keyType:
+ description: |-
+ The type of keypair Kubelet will generate for the pod.
+
+ Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384",
+ "ECDSAP521", and "ED25519".
+ type: string
+ maxExpirationSeconds:
+ description: |-
+ maxExpirationSeconds is the maximum lifetime permitted for the
+ certificate.
+
+ Kubelet copies this value verbatim into the PodCertificateRequests it
+ generates for this projection.
+
+ If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver
+ will reject values shorter than 3600 (1 hour). The maximum allowable
+ value is 7862400 (91 days).
+
+ The signer implementation is then free to issue a certificate with any
+ lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600
+ seconds (1 hour). This constraint is enforced by kube-apiserver.
+ `kubernetes.io` signers will never issue certificates with a lifetime
+ longer than 24 hours.
+ format: int32
+ type: integer
+ signerName:
+ description: Kubelet's generated CSRs will be
+ addressed to this signer.
+ type: string
+ required:
+ - keyType
+ - signerName
+ type: object
secret:
description: secret information about the secret data
to project
@@ -7064,7 +7389,6 @@ spec:
description: |-
rbd represents a Rados Block Device mount on the host that shares a pod's lifetime.
Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.
- More info: https://examples.k8s.io/volumes/rbd/README.md
properties:
fsType:
description: |-
diff --git a/pkg/component/observability/plutono/plutono_test.go b/pkg/component/observability/plutono/plutono_test.go
index 11086be19c4..91ce11abd75 100644
--- a/pkg/component/observability/plutono/plutono_test.go
+++ b/pkg/component/observability/plutono/plutono_test.go
@@ -166,7 +166,6 @@ data:
immutable: true
kind: ConfigMap
metadata:
- creationTimestamp: null
labels:
component: plutono
resources.gardener.cloud/garbage-collectable-reference: "true"
@@ -254,7 +253,6 @@ data:
` + configMapData + `
kind: ConfigMap
metadata:
- creationTimestamp: null
labels:
component: plutono
datasource.monitoring.gardener.cloud/` + clusterLabelKey(values) + `: "true"
@@ -491,7 +489,6 @@ metadata:
out := `apiVersion: v1
kind: Service
metadata:
- creationTimestamp: null
labels:
component: plutono
`
@@ -542,7 +539,6 @@ metadata:
location /api/admin/ {
return 403;
}
- creationTimestamp: null
`
if values.ClusterType == comp.ClusterTypeShoot {
out += ` labels:
diff --git a/pkg/component/seed/system/system_test.go b/pkg/component/seed/system/system_test.go
index 4eb02dc8af1..b74bc70ccc3 100644
--- a/pkg/component/seed/system/system_test.go
+++ b/pkg/component/seed/system/system_test.go
@@ -50,7 +50,6 @@ kind: Deployment
metadata:
annotations:
resources.gardener.cloud/skip-health-check: "true"
- creationTimestamp: null
labels:
app: kubernetes
role: reserve-excess-capacity
@@ -66,7 +65,6 @@ spec:
strategy: {}
template:
metadata:
- creationTimestamp: null
labels:
app: kubernetes
role: reserve-excess-capacity
@@ -93,7 +91,6 @@ kind: Deployment
metadata:
annotations:
resources.gardener.cloud/skip-health-check: "true"
- creationTimestamp: null
labels:
app: kubernetes
role: reserve-excess-capacity
@@ -109,7 +106,6 @@ spec:
strategy: {}
template:
metadata:
- creationTimestamp: null
labels:
app: kubernetes
role: reserve-excess-capacity
@@ -375,7 +371,6 @@ func expectedPriorityClasses() []string {
description: `+pc.description+`
kind: PriorityClass
metadata:
- creationTimestamp: null
name: `+pc.name+`
value: `+strconv.FormatInt(int64(pc.value), 10)+`
`)
diff --git a/pkg/component/shared/kubeapiserver_test.go b/pkg/component/shared/kubeapiserver_test.go
index 8d12882fddb..f48301b902e 100644
--- a/pkg/component/shared/kubeapiserver_test.go
+++ b/pkg/component/shared/kubeapiserver_test.go
@@ -929,7 +929,9 @@ authorizers:
Kubeconfig: []byte("webhook-kubeconfig"),
WebhookConfiguration: apiserverv1beta1.WebhookConfiguration{
AuthorizedTTL: metav1.Duration{Duration: 5 * time.Minute},
+ CacheAuthorizedRequests: ptr.To(true),
UnauthorizedTTL: metav1.Duration{Duration: 30 * time.Second},
+ CacheUnauthorizedRequests: ptr.To(true),
Timeout: metav1.Duration{Duration: 3 * time.Second},
SubjectAccessReviewVersion: "v1",
MatchConditionSubjectAccessReviewVersion: "v1",
diff --git a/pkg/controller/networkpolicy/add.go b/pkg/controller/networkpolicy/add.go
index 08a94b64467..58a3b8d5b37 100644
--- a/pkg/controller/networkpolicy/add.go
+++ b/pkg/controller/networkpolicy/add.go
@@ -28,6 +28,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"
"github.com/gardener/gardener/pkg/controller/networkpolicy/hostnameresolver"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -69,6 +70,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, runtimeCluster cluster.Cl
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(source.Kind[client.Object](
runtimeCluster.GetCache(),
diff --git a/pkg/controller/networkpolicy/reconciler.go b/pkg/controller/networkpolicy/reconciler.go
index e3fc0b61edf..37bf0e9145a 100644
--- a/pkg/controller/networkpolicy/reconciler.go
+++ b/pkg/controller/networkpolicy/reconciler.go
@@ -86,9 +86,6 @@ func (r RuntimeNetworkConfig) getBlockedNetworkPeers(ipFamily gardencorev1beta1.
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
namespace := &corev1.Namespace{}
if err := r.RuntimeClient.Get(ctx, request.NamespacedName, namespace); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controller/reference/add.go b/pkg/controller/reference/add.go
index a1b9739dd65..19e3fbb8ab8 100644
--- a/pkg/controller/reference/add.go
+++ b/pkg/controller/reference/add.go
@@ -14,6 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// controllerNameSuffix is the suffix added to the controller name.
@@ -31,6 +32,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, name string) error {
For(r.NewObjectFunc(), builder.WithPredicates(r.Predicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controller/reference/reconciler.go b/pkg/controller/reference/reconciler.go
index ac3a8f46ad5..2f9c4f76761 100644
--- a/pkg/controller/reference/reconciler.go
+++ b/pkg/controller/reference/reconciler.go
@@ -46,9 +46,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
obj := r.NewObjectFunc()
if err := r.Client.Get(ctx, request.NamespacedName, obj); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controller/tokenrequestor/add.go b/pkg/controller/tokenrequestor/add.go
index 37613f54101..ab3b41fb893 100644
--- a/pkg/controller/tokenrequestor/add.go
+++ b/pkg/controller/tokenrequestor/add.go
@@ -17,6 +17,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of the controller.
@@ -46,6 +47,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, sourceCluster, targetClus
For(&corev1.Secret{}, builder.WithPredicates(r.SecretPredicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: r.ConcurrentSyncs,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controller/tokenrequestor/reconciler.go b/pkg/controller/tokenrequestor/reconciler.go
index 51d7d5ecb1d..e584645f69d 100644
--- a/pkg/controller/tokenrequestor/reconciler.go
+++ b/pkg/controller/tokenrequestor/reconciler.go
@@ -28,7 +28,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
)
const (
@@ -53,11 +52,8 @@ type Reconciler struct {
}
// Reconcile requests and populates tokens.
-func (r *Reconciler) Reconcile(reconcileCtx context.Context, req reconcile.Request) (reconcile.Result, error) {
- log := logf.FromContext(reconcileCtx)
-
- ctx, cancel := controllerutils.GetMainReconciliationContext(reconcileCtx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
+func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
+ log := logf.FromContext(ctx)
secret := &corev1.Secret{}
if err := r.SourceClient.Get(ctx, req.NamespacedName, secret); err != nil {
diff --git a/pkg/controller/tokenrequestor/reconciler_test.go b/pkg/controller/tokenrequestor/reconciler_test.go
index c36629050ea..f9b87e2bd8a 100644
--- a/pkg/controller/tokenrequestor/reconciler_test.go
+++ b/pkg/controller/tokenrequestor/reconciler_test.go
@@ -545,7 +545,6 @@ contexts:
name: shoot--foo--bar
current-context: shoot--foo--bar
kind: Config
-preferences: {}
users:
- name: shoot--foo--bar-token
user:
diff --git a/pkg/controller/vpaevictionrequirements/add.go b/pkg/controller/vpaevictionrequirements/add.go
index 09bf9e9851e..5f91ab407c5 100644
--- a/pkg/controller/vpaevictionrequirements/add.go
+++ b/pkg/controller/vpaevictionrequirements/add.go
@@ -21,6 +21,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"
"github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -48,6 +49,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, seedCluster cluster.Clust
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(
source.Kind[client.Object](seedCluster.GetCache(),
diff --git a/pkg/controller/vpaevictionrequirements/reconciler.go b/pkg/controller/vpaevictionrequirements/reconciler.go
index e516d37ee2a..83504586201 100644
--- a/pkg/controller/vpaevictionrequirements/reconciler.go
+++ b/pkg/controller/vpaevictionrequirements/reconciler.go
@@ -21,7 +21,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
- "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils/timewindow"
)
@@ -40,8 +39,6 @@ type Reconciler struct {
// Reconcile implements the reconciliation logic for adding/removing EvictionRequirements to VPA objects.
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
vpa := &vpaautoscalingv1.VerticalPodAutoscaler{}
if err := r.SeedClient.Get(ctx, request.NamespacedName, vpa); err != nil {
diff --git a/pkg/controllermanager/apis/config/v1alpha1/validation/validation_test.go b/pkg/controllermanager/apis/config/v1alpha1/validation/validation_test.go
index 8d286b10954..ec19757b11c 100644
--- a/pkg/controllermanager/apis/config/v1alpha1/validation/validation_test.go
+++ b/pkg/controllermanager/apis/config/v1alpha1/validation/validation_test.go
@@ -88,7 +88,7 @@ var _ = Describe("#ValidateControllerManagerConfiguration", func() {
Expect(ValidateControllerManagerConfiguration(conf)).To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
+ "Type": Equal(field.ErrorTypeRequired),
"Field": Equal("leaderElection.resourceNamespace"),
})),
))
diff --git a/pkg/controllermanager/controller/bastion/add.go b/pkg/controllermanager/controller/bastion/add.go
index d235e0816c7..07752758980 100644
--- a/pkg/controllermanager/controller/bastion/add.go
+++ b/pkg/controllermanager/controller/bastion/add.go
@@ -23,6 +23,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/apis/operations"
operationsv1alpha1 "github.com/gardener/gardener/pkg/apis/operations/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/controllerutils/mapper"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -45,6 +46,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&operationsv1alpha1.Bastion{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Watches(
&gardencorev1beta1.Shoot{},
diff --git a/pkg/controllermanager/controller/bastion/reconciler.go b/pkg/controllermanager/controller/bastion/reconciler.go
index 44bae20c830..ac2dab4977b 100644
--- a/pkg/controllermanager/controller/bastion/reconciler.go
+++ b/pkg/controllermanager/controller/bastion/reconciler.go
@@ -18,7 +18,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
operationsv1alpha1 "github.com/gardener/gardener/pkg/apis/operations/v1alpha1"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
)
// Reconciler reconciles Bastions.
@@ -32,9 +31,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
bastion := &operationsv1alpha1.Bastion{}
if err := r.Client.Get(ctx, request.NamespacedName, bastion); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/certificatesigningrequest/add.go b/pkg/controllermanager/controller/certificatesigningrequest/add.go
index 4a9ce5215b3..9ce3009a147 100644
--- a/pkg/controllermanager/controller/certificatesigningrequest/add.go
+++ b/pkg/controllermanager/controller/certificatesigningrequest/add.go
@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/manager"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -29,6 +30,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&certificatesv1.CertificateSigningRequest{}, builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create, predicateutils.Update))).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/certificatesigningrequest/reconciler.go b/pkg/controllermanager/controller/certificatesigningrequest/reconciler.go
index b6c63998e7e..686dc0ddead 100644
--- a/pkg/controllermanager/controller/certificatesigningrequest/reconciler.go
+++ b/pkg/controllermanager/controller/certificatesigningrequest/reconciler.go
@@ -43,7 +43,6 @@ import (
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
"github.com/gardener/gardener/pkg/client/kubernetes"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
gardenletutils "github.com/gardener/gardener/pkg/utils/gardener/gardenlet"
@@ -65,9 +64,6 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
finalState string
)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
csr := &certificatesv1.CertificateSigningRequest{}
if err := r.Client.Get(ctx, request.NamespacedName, csr); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/cloudprofile/add.go b/pkg/controllermanager/controller/cloudprofile/add.go
index ba67fcd462f..05e4fd51b78 100644
--- a/pkg/controllermanager/controller/cloudprofile/add.go
+++ b/pkg/controllermanager/controller/cloudprofile/add.go
@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -31,6 +32,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.CloudProfile{}).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/cloudprofile/reconciler.go b/pkg/controllermanager/controller/cloudprofile/reconciler.go
index 51ca7507265..7b3fe07d4ef 100644
--- a/pkg/controllermanager/controller/cloudprofile/reconciler.go
+++ b/pkg/controllermanager/controller/cloudprofile/reconciler.go
@@ -35,9 +35,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
cloudProfile := &gardencorev1beta1.CloudProfile{}
if err := r.Client.Get(ctx, request.NamespacedName, cloudProfile); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/controllerdeployment/add.go b/pkg/controllermanager/controller/controllerdeployment/add.go
index 409fb808214..340698681a3 100644
--- a/pkg/controllermanager/controller/controllerdeployment/add.go
+++ b/pkg/controllermanager/controller/controllerdeployment/add.go
@@ -12,6 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
gardencorev1 "github.com/gardener/gardener/pkg/apis/core/v1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
const (
@@ -34,6 +35,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
RateLimiter: r.RateLimiter,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/controllerdeployment/reconciler.go b/pkg/controllermanager/controller/controllerdeployment/reconciler.go
index 6c44a0ff724..73cee294cab 100644
--- a/pkg/controllermanager/controller/controllerdeployment/reconciler.go
+++ b/pkg/controllermanager/controller/controllerdeployment/reconciler.go
@@ -35,9 +35,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
controllerDeployment := &gardencorev1.ControllerDeployment{}
if err := r.Client.Get(ctx, client.ObjectKey{Name: req.Name}, controllerDeployment); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/add.go b/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/add.go
index 134c1416cf1..a9528181c70 100644
--- a/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/add.go
+++ b/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/add.go
@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -28,6 +29,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.ControllerRegistration{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})).
WithOptions(controller.Options{
MaxConcurrentReconciles: 5,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler.go b/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler.go
index ecba930f692..fcf9956c60d 100644
--- a/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler.go
+++ b/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler.go
@@ -34,9 +34,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
controllerRegistration := &gardencorev1beta1.ControllerRegistration{}
if err := r.Client.Get(ctx, request.NamespacedName, controllerRegistration); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/controllerregistration/extensionclusterrole/add.go b/pkg/controllermanager/controller/controllerregistration/extensionclusterrole/add.go
index 4ed0dfd3c72..d49bdd6110b 100644
--- a/pkg/controllermanager/controller/controllerregistration/extensionclusterrole/add.go
+++ b/pkg/controllermanager/controller/controllerregistration/extensionclusterrole/add.go
@@ -27,6 +27,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
)
@@ -64,7 +65,10 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
ControllerManagedBy(mgr).
Named(ControllerName).
For(clusterRole, builder.WithPredicates(labelSelectorPredicate)).
- WithOptions(controller.Options{MaxConcurrentReconciles: 5}).
+ WithOptions(controller.Options{
+ MaxConcurrentReconciles: 5,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
+ }).
Watches(
serviceAccount,
handler.EnqueueRequestsFromMapFunc(r.MapToMatchingClusterRoles(mgr.GetLogger().WithValues("controller", ControllerName))),
diff --git a/pkg/controllermanager/controller/controllerregistration/extensionclusterrole/reconciler.go b/pkg/controllermanager/controller/controllerregistration/extensionclusterrole/reconciler.go
index 954f5f05a36..3def65afc2b 100644
--- a/pkg/controllermanager/controller/controllerregistration/extensionclusterrole/reconciler.go
+++ b/pkg/controllermanager/controller/controllerregistration/extensionclusterrole/reconciler.go
@@ -35,9 +35,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
clusterRole := &metav1.PartialObjectMetadata{}
clusterRole.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind("ClusterRole"))
if err := r.Client.Get(ctx, request.NamespacedName, clusterRole); err != nil {
diff --git a/pkg/controllermanager/controller/controllerregistration/seed/add.go b/pkg/controllermanager/controller/controllerregistration/seed/add.go
index 000a8240128..12d103b4c45 100644
--- a/pkg/controllermanager/controller/controllerregistration/seed/add.go
+++ b/pkg/controllermanager/controller/controllerregistration/seed/add.go
@@ -24,6 +24,7 @@ import (
gardencorev1 "github.com/gardener/gardener/pkg/apis/core/v1"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
+ "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/controllerutils/mapper"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -46,6 +47,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Seed{}, builder.WithPredicates(r.SeedPredicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Watches(
&gardencorev1beta1.ControllerRegistration{},
diff --git a/pkg/controllermanager/controller/controllerregistration/seed/reconciler.go b/pkg/controllermanager/controller/controllerregistration/seed/reconciler.go
index fb434b51d6d..6961731a62c 100644
--- a/pkg/controllermanager/controller/controllerregistration/seed/reconciler.go
+++ b/pkg/controllermanager/controller/controllerregistration/seed/reconciler.go
@@ -57,9 +57,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
seed := &gardencorev1beta1.Seed{}
if err := r.Client.Get(ctx, request.NamespacedName, seed); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/controllerregistration/seedfinalizer/add.go b/pkg/controllermanager/controller/controllerregistration/seedfinalizer/add.go
index 8bbd2c331a2..e9e6df7fc64 100644
--- a/pkg/controllermanager/controller/controllerregistration/seedfinalizer/add.go
+++ b/pkg/controllermanager/controller/controllerregistration/seedfinalizer/add.go
@@ -17,6 +17,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -35,6 +36,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Seed{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})).
WithOptions(controller.Options{
MaxConcurrentReconciles: 5,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Watches(
&gardencorev1beta1.ControllerInstallation{},
diff --git a/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler.go b/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler.go
index a17366ed710..fec718ac872 100644
--- a/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler.go
+++ b/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler.go
@@ -34,9 +34,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
seed := &gardencorev1beta1.Seed{}
if err := r.Client.Get(ctx, request.NamespacedName, seed); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/credentialsbinding/add.go b/pkg/controllermanager/controller/credentialsbinding/add.go
index 903d6f6e1b5..d6d9e7fca58 100644
--- a/pkg/controllermanager/controller/credentialsbinding/add.go
+++ b/pkg/controllermanager/controller/credentialsbinding/add.go
@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -31,6 +32,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&securityv1alpha1.CredentialsBinding{}).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/credentialsbinding/reconciler.go b/pkg/controllermanager/controller/credentialsbinding/reconciler.go
index c8928a8ea3c..7b63d622ed5 100644
--- a/pkg/controllermanager/controller/credentialsbinding/reconciler.go
+++ b/pkg/controllermanager/controller/credentialsbinding/reconciler.go
@@ -16,6 +16,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -23,6 +24,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
+ "github.com/gardener/gardener/pkg/client/kubernetes"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils"
@@ -42,9 +44,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
credentialsBinding := &securityv1alpha1.CredentialsBinding{}
if err := r.Client.Get(ctx, request.NamespacedName, credentialsBinding); err != nil {
if apierrors.IsNotFound(err) {
@@ -78,7 +77,11 @@ func (r *Reconciler) reconcile(ctx context.Context, credentialsBinding *security
if err != nil {
return err
}
- kind := credential.GetObjectKind().GroupVersionKind().Kind
+ gvk, err := apiutil.GVKForObject(credential, kubernetes.GardenScheme)
+ if err != nil {
+ return err
+ }
+ kind := gvk.Kind
if !controllerutil.ContainsFinalizer(credential, finalizerName) {
log.Info("Adding finalizer", "finalizer", finalizerName, kind, client.ObjectKeyFromObject(credential)) //nolint:logcheck
@@ -100,8 +103,8 @@ func (r *Reconciler) reconcile(ctx context.Context, credentialsBinding *security
_, hasProviderKeyLabel := labels[providerTypeLabelKey]
_, hasCredentialsBindingRefLabel := labels[v1beta1constants.LabelCredentialsBindingReference]
- secretNeedsLabel := !hasProviderKeyLabel && credential.GetObjectKind().GroupVersionKind().Kind == "Secret"
- workloadIdentityNeedsLabelRemoval := hasProviderKeyLabel && credential.GetObjectKind().GroupVersionKind().Kind == "WorkloadIdentity"
+ secretNeedsLabel := !hasProviderKeyLabel && kind == "Secret"
+ workloadIdentityNeedsLabelRemoval := hasProviderKeyLabel && kind == "WorkloadIdentity"
if secretNeedsLabel || workloadIdentityNeedsLabelRemoval || !hasCredentialsBindingRefLabel {
patch := client.MergeFrom(credential.DeepCopyObject().(client.Object))
if secretNeedsLabel {
diff --git a/pkg/controllermanager/controller/event/add.go b/pkg/controllermanager/controller/event/add.go
index 7e2da50da50..04963742a3c 100644
--- a/pkg/controllermanager/controller/event/add.go
+++ b/pkg/controllermanager/controller/event/add.go
@@ -12,6 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/manager"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -33,6 +34,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&corev1.Event{}, builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create))).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/event/reconciler.go b/pkg/controllermanager/controller/event/reconciler.go
index 8115f669615..0f4f007001e 100644
--- a/pkg/controllermanager/controller/event/reconciler.go
+++ b/pkg/controllermanager/controller/event/reconciler.go
@@ -18,7 +18,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
)
// Reconciler reconciles Event.
@@ -32,9 +31,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
event := &corev1.Event{}
if err := r.Client.Get(ctx, req.NamespacedName, event); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/exposureclass/add.go b/pkg/controllermanager/controller/exposureclass/add.go
index 640ef3465d9..dd1a062e549 100644
--- a/pkg/controllermanager/controller/exposureclass/add.go
+++ b/pkg/controllermanager/controller/exposureclass/add.go
@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -32,6 +33,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
RateLimiter: r.RateLimiter,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/exposureclass/reconciler.go b/pkg/controllermanager/controller/exposureclass/reconciler.go
index cddfc8cf746..5e543b741f6 100644
--- a/pkg/controllermanager/controller/exposureclass/reconciler.go
+++ b/pkg/controllermanager/controller/exposureclass/reconciler.go
@@ -38,9 +38,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
exposureClass := &gardencorev1beta1.ExposureClass{}
if err := r.Client.Get(ctx, request.NamespacedName, exposureClass); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/managedseedset/add.go b/pkg/controllermanager/controller/managedseedset/add.go
index dab297ef634..cc729639615 100644
--- a/pkg/controllermanager/controller/managedseedset/add.go
+++ b/pkg/controllermanager/controller/managedseedset/add.go
@@ -49,6 +49,7 @@ func (r *Reconciler) AddToManager(ctx context.Context, mgr manager.Manager) erro
For(&seedmanagementv1alpha1.ManagedSeedSet{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
Watches(
&gardencorev1beta1.Shoot{},
diff --git a/pkg/controllermanager/controller/managedseedset/reconciler.go b/pkg/controllermanager/controller/managedseedset/reconciler.go
index 58231b75373..bad2d2b3787 100644
--- a/pkg/controllermanager/controller/managedseedset/reconciler.go
+++ b/pkg/controllermanager/controller/managedseedset/reconciler.go
@@ -32,9 +32,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
managedSeedSet := &seedmanagementv1alpha1.ManagedSeedSet{}
if err := r.Client.Get(ctx, request.NamespacedName, managedSeedSet); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/namespacedcloudprofile/add.go b/pkg/controllermanager/controller/namespacedcloudprofile/add.go
index 4517b96ee66..e64c39bb472 100644
--- a/pkg/controllermanager/controller/namespacedcloudprofile/add.go
+++ b/pkg/controllermanager/controller/namespacedcloudprofile/add.go
@@ -40,6 +40,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.NamespacedCloudProfile{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Watches(
&gardencorev1beta1.CloudProfile{},
diff --git a/pkg/controllermanager/controller/namespacedcloudprofile/reconciler.go b/pkg/controllermanager/controller/namespacedcloudprofile/reconciler.go
index d692774aea1..b7b5fde79bf 100644
--- a/pkg/controllermanager/controller/namespacedcloudprofile/reconciler.go
+++ b/pkg/controllermanager/controller/namespacedcloudprofile/reconciler.go
@@ -40,9 +40,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
namespacedCloudProfile := &gardencorev1beta1.NamespacedCloudProfile{}
if err := r.Client.Get(ctx, request.NamespacedName, namespacedCloudProfile); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/project/activity/add.go b/pkg/controllermanager/controller/project/activity/add.go
index 1218534d2c5..f22b4b9b525 100644
--- a/pkg/controllermanager/controller/project/activity/add.go
+++ b/pkg/controllermanager/controller/project/activity/add.go
@@ -26,6 +26,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ "github.com/gardener/gardener/pkg/controllerutils"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
)
@@ -46,6 +47,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Watches(
&gardencorev1beta1.Shoot{},
diff --git a/pkg/controllermanager/controller/project/activity/reconciler.go b/pkg/controllermanager/controller/project/activity/reconciler.go
index 8f133962707..88ebc3d56de 100644
--- a/pkg/controllermanager/controller/project/activity/reconciler.go
+++ b/pkg/controllermanager/controller/project/activity/reconciler.go
@@ -17,7 +17,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
)
// Reconciler reconciles Projects and updates the lastActivityTimestamp in the status.
@@ -31,9 +30,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
project := &gardencorev1beta1.Project{}
if err := r.Client.Get(ctx, request.NamespacedName, project); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/project/project/add.go b/pkg/controllermanager/controller/project/project/add.go
index 9045a16def8..79c35463b4d 100644
--- a/pkg/controllermanager/controller/project/project/add.go
+++ b/pkg/controllermanager/controller/project/project/add.go
@@ -16,6 +16,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -40,6 +41,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
RateLimiter: r.RateLimiter,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/project/project/reconciler.go b/pkg/controllermanager/controller/project/project/reconciler.go
index f3736584f79..19acc6eb524 100644
--- a/pkg/controllermanager/controller/project/project/reconciler.go
+++ b/pkg/controllermanager/controller/project/project/reconciler.go
@@ -51,9 +51,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
project := &gardencorev1beta1.Project{}
if err := r.Client.Get(ctx, request.NamespacedName, project); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/project/stale/add.go b/pkg/controllermanager/controller/project/stale/add.go
index 752a368971c..6ba28f296a2 100644
--- a/pkg/controllermanager/controller/project/stale/add.go
+++ b/pkg/controllermanager/controller/project/stale/add.go
@@ -36,6 +36,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Project{}, builder.WithPredicates(r.ProjectPredicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.StaleSyncPeriod.Duration,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/project/stale/reconciler.go b/pkg/controllermanager/controller/project/stale/reconciler.go
index 7f421bfd69f..89654c7a059 100644
--- a/pkg/controllermanager/controller/project/stale/reconciler.go
+++ b/pkg/controllermanager/controller/project/stale/reconciler.go
@@ -25,7 +25,6 @@ import (
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
)
@@ -41,9 +40,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.StaleSyncPeriod.Duration)
- defer cancel()
-
project := &gardencorev1beta1.Project{}
if err := r.Client.Get(ctx, request.NamespacedName, project); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/quota/add.go b/pkg/controllermanager/controller/quota/add.go
index bdc20f38680..a172ce9e8ed 100644
--- a/pkg/controllermanager/controller/quota/add.go
+++ b/pkg/controllermanager/controller/quota/add.go
@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -31,6 +32,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Quota{}).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/quota/reconciler.go b/pkg/controllermanager/controller/quota/reconciler.go
index 82dbcb9d044..ce20a5bd0c2 100644
--- a/pkg/controllermanager/controller/quota/reconciler.go
+++ b/pkg/controllermanager/controller/quota/reconciler.go
@@ -34,9 +34,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
quota := &gardencorev1beta1.Quota{}
if err := r.Client.Get(ctx, request.NamespacedName, quota); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/secretbinding/add.go b/pkg/controllermanager/controller/secretbinding/add.go
index f892f0d50e4..5e3453a889d 100644
--- a/pkg/controllermanager/controller/secretbinding/add.go
+++ b/pkg/controllermanager/controller/secretbinding/add.go
@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -31,6 +32,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.SecretBinding{}).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/secretbinding/reconciler.go b/pkg/controllermanager/controller/secretbinding/reconciler.go
index afd9c2bf0ec..05362addee7 100644
--- a/pkg/controllermanager/controller/secretbinding/reconciler.go
+++ b/pkg/controllermanager/controller/secretbinding/reconciler.go
@@ -39,9 +39,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
secretBinding := &gardencorev1beta1.SecretBinding{}
if err := r.Client.Get(ctx, request.NamespacedName, secretBinding); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/seed/backupbucketscheck/add.go b/pkg/controllermanager/controller/seed/backupbucketscheck/add.go
index ed601aaa4f7..2e4e83cb14c 100644
--- a/pkg/controllermanager/controller/seed/backupbucketscheck/add.go
+++ b/pkg/controllermanager/controller/seed/backupbucketscheck/add.go
@@ -39,6 +39,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
Watches(
&gardencorev1beta1.BackupBucket{},
diff --git a/pkg/controllermanager/controller/seed/backupbucketscheck/reconciler.go b/pkg/controllermanager/controller/seed/backupbucketscheck/reconciler.go
index 556ad33bede..b9008a2d624 100644
--- a/pkg/controllermanager/controller/seed/backupbucketscheck/reconciler.go
+++ b/pkg/controllermanager/controller/seed/backupbucketscheck/reconciler.go
@@ -19,7 +19,6 @@ import (
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/controllermanager/controller/seed/utils"
- "github.com/gardener/gardener/pkg/controllerutils"
)
// Reconciler reconciles Seeds and maintains the BackupBucketsReady condition according to the observed status of the
@@ -35,9 +34,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
seed := &gardencorev1beta1.Seed{}
if err := r.Client.Get(ctx, req.NamespacedName, seed); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/seed/extensionscheck/add.go b/pkg/controllermanager/controller/seed/extensionscheck/add.go
index 6e5453c2b4c..3c654291674 100644
--- a/pkg/controllermanager/controller/seed/extensionscheck/add.go
+++ b/pkg/controllermanager/controller/seed/extensionscheck/add.go
@@ -38,6 +38,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
Watches(
&gardencorev1beta1.ControllerInstallation{},
diff --git a/pkg/controllermanager/controller/seed/extensionscheck/reconciler.go b/pkg/controllermanager/controller/seed/extensionscheck/reconciler.go
index 0a3afa37b45..fa04eb753de 100644
--- a/pkg/controllermanager/controller/seed/extensionscheck/reconciler.go
+++ b/pkg/controllermanager/controller/seed/extensionscheck/reconciler.go
@@ -20,7 +20,6 @@ import (
"github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/controllermanager/controller/seed/utils"
- "github.com/gardener/gardener/pkg/controllerutils"
)
var conditionsToCheck = []gardencorev1beta1.ConditionType{
@@ -43,9 +42,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
seed := &gardencorev1beta1.Seed{}
if err := r.Client.Get(ctx, request.NamespacedName, seed); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/seed/lifecycle/add.go b/pkg/controllermanager/controller/seed/lifecycle/add.go
index 6180f4730a8..6e093a9067d 100644
--- a/pkg/controllermanager/controller/seed/lifecycle/add.go
+++ b/pkg/controllermanager/controller/seed/lifecycle/add.go
@@ -36,6 +36,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Seed{}, builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create))).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/seed/lifecycle/reconciler.go b/pkg/controllermanager/controller/seed/lifecycle/reconciler.go
index c5d5408aa87..6e0778f5ed9 100644
--- a/pkg/controllermanager/controller/seed/lifecycle/reconciler.go
+++ b/pkg/controllermanager/controller/seed/lifecycle/reconciler.go
@@ -21,7 +21,6 @@ import (
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils/flow"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
@@ -43,9 +42,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
seed := &gardencorev1beta1.Seed{}
if err := r.Client.Get(ctx, req.NamespacedName, seed); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/seed/secrets/add.go b/pkg/controllermanager/controller/seed/secrets/add.go
index 4b065836ee7..276bc88f0d2 100644
--- a/pkg/controllermanager/controller/seed/secrets/add.go
+++ b/pkg/controllermanager/controller/seed/secrets/add.go
@@ -24,6 +24,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/controllerutils/mapper"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
"github.com/gardener/gardener/pkg/utils"
@@ -48,6 +49,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Seed{}, builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create))).
WithOptions(controller.Options{
MaxConcurrentReconciles: 5,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Watches(
&corev1.Secret{},
diff --git a/pkg/controllermanager/controller/seed/secrets/reconciler.go b/pkg/controllermanager/controller/seed/secrets/reconciler.go
index 73453e9eb6b..2039af0b708 100644
--- a/pkg/controllermanager/controller/seed/secrets/reconciler.go
+++ b/pkg/controllermanager/controller/seed/secrets/reconciler.go
@@ -35,9 +35,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
seed := &gardencorev1beta1.Seed{}
if err := r.Client.Get(ctx, req.NamespacedName, seed); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/shoot/conditions/add.go b/pkg/controllermanager/controller/shoot/conditions/add.go
index 3e6ac58af31..a2b76fd0fc5 100644
--- a/pkg/controllermanager/controller/shoot/conditions/add.go
+++ b/pkg/controllermanager/controller/shoot/conditions/add.go
@@ -24,6 +24,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -42,6 +43,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Shoot{}, builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create))).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Watches(
&gardencorev1beta1.Seed{},
diff --git a/pkg/controllermanager/controller/shoot/conditions/reconciler.go b/pkg/controllermanager/controller/shoot/conditions/reconciler.go
index 415ea8a3631..c466c7c1e4a 100644
--- a/pkg/controllermanager/controller/shoot/conditions/reconciler.go
+++ b/pkg/controllermanager/controller/shoot/conditions/reconciler.go
@@ -16,7 +16,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
)
@@ -31,9 +30,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.Client.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/shoot/hibernation/add.go b/pkg/controllermanager/controller/shoot/hibernation/add.go
index fe86a6a0906..541353d57a7 100644
--- a/pkg/controllermanager/controller/shoot/hibernation/add.go
+++ b/pkg/controllermanager/controller/shoot/hibernation/add.go
@@ -16,6 +16,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -39,6 +40,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Shoot{}, builder.WithPredicates(r.ShootPredicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/shoot/hibernation/reconciler.go b/pkg/controllermanager/controller/shoot/hibernation/reconciler.go
index 7ab527e3f1f..faedb7d92fc 100644
--- a/pkg/controllermanager/controller/shoot/hibernation/reconciler.go
+++ b/pkg/controllermanager/controller/shoot/hibernation/reconciler.go
@@ -23,7 +23,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
)
@@ -80,9 +79,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.Client.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/shoot/maintenance/add.go b/pkg/controllermanager/controller/shoot/maintenance/add.go
index 20dd2842a91..4c012b75140 100644
--- a/pkg/controllermanager/controller/shoot/maintenance/add.go
+++ b/pkg/controllermanager/controller/shoot/maintenance/add.go
@@ -15,6 +15,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -38,6 +39,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Shoot{}, builder.WithPredicates(r.ShootPredicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/shoot/maintenance/reconciler.go b/pkg/controllermanager/controller/shoot/maintenance/reconciler.go
index ee9440fef18..5bc6f29379e 100644
--- a/pkg/controllermanager/controller/shoot/maintenance/reconciler.go
+++ b/pkg/controllermanager/controller/shoot/maintenance/reconciler.go
@@ -49,9 +49,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.Client.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/shoot/migration/add.go b/pkg/controllermanager/controller/shoot/migration/add.go
index 6cc6ad4bddc..95d396be4d1 100644
--- a/pkg/controllermanager/controller/shoot/migration/add.go
+++ b/pkg/controllermanager/controller/shoot/migration/add.go
@@ -14,6 +14,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -31,6 +32,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Shoot{}, builder.WithPredicates(r.ShootPredicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/shoot/migration/reconciler.go b/pkg/controllermanager/controller/shoot/migration/reconciler.go
index 259fb48e0e6..a0d0fb2c2c8 100644
--- a/pkg/controllermanager/controller/shoot/migration/reconciler.go
+++ b/pkg/controllermanager/controller/shoot/migration/reconciler.go
@@ -18,7 +18,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils/kubernetes/health"
)
@@ -34,9 +33,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.Client.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/shoot/quota/add.go b/pkg/controllermanager/controller/shoot/quota/add.go
index a94b5da83f1..90497b8ef77 100644
--- a/pkg/controllermanager/controller/shoot/quota/add.go
+++ b/pkg/controllermanager/controller/shoot/quota/add.go
@@ -33,6 +33,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Shoot{}, builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create))).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/shoot/quota/reconciler.go b/pkg/controllermanager/controller/shoot/quota/reconciler.go
index cc587c096d6..05c9e2f5941 100644
--- a/pkg/controllermanager/controller/shoot/quota/reconciler.go
+++ b/pkg/controllermanager/controller/shoot/quota/reconciler.go
@@ -20,7 +20,6 @@ import (
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
)
@@ -35,9 +34,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.Client.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/shoot/retry/add.go b/pkg/controllermanager/controller/shoot/retry/add.go
index b2b1a73b519..f07834e74e2 100644
--- a/pkg/controllermanager/controller/shoot/retry/add.go
+++ b/pkg/controllermanager/controller/shoot/retry/add.go
@@ -14,6 +14,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -31,6 +32,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Shoot{}, builder.WithPredicates(r.ShootPredicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/shoot/retry/reconciler.go b/pkg/controllermanager/controller/shoot/retry/reconciler.go
index f9623df5575..c6b18ae161e 100644
--- a/pkg/controllermanager/controller/shoot/retry/reconciler.go
+++ b/pkg/controllermanager/controller/shoot/retry/reconciler.go
@@ -18,7 +18,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils"
)
@@ -32,9 +31,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.Client.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllermanager/controller/shoot/statuslabel/add.go b/pkg/controllermanager/controller/shoot/statuslabel/add.go
index 643b41a35c4..58ae178b4ee 100644
--- a/pkg/controllermanager/controller/shoot/statuslabel/add.go
+++ b/pkg/controllermanager/controller/shoot/statuslabel/add.go
@@ -14,6 +14,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ "github.com/gardener/gardener/pkg/controllerutils"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
)
@@ -32,6 +33,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Shoot{}, builder.WithPredicates(r.ShootPredicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/controllermanager/controller/shoot/statuslabel/reconciler.go b/pkg/controllermanager/controller/shoot/statuslabel/reconciler.go
index 12cb08a606f..4700134d586 100644
--- a/pkg/controllermanager/controller/shoot/statuslabel/reconciler.go
+++ b/pkg/controllermanager/controller/shoot/statuslabel/reconciler.go
@@ -17,7 +17,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
)
@@ -31,9 +30,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.Client.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/controllerutils/miscellaneous.go b/pkg/controllerutils/miscellaneous.go
index 5f8e50f0037..2b8b8bf5cc7 100644
--- a/pkg/controllerutils/miscellaneous.go
+++ b/pkg/controllerutils/miscellaneous.go
@@ -77,14 +77,6 @@ func setTaskAnnotations(annotations map[string]string, tasks []string) {
annotations[v1beta1constants.ShootTasks] = strings.Join(tasks, separator)
}
-// GetMainReconciliationContext returns a context with timeout for the controller's main client. The resulting context has a timeout equal to the timeout passed in the argument but
-// not more than DefaultReconciliationTimeout.
-func GetMainReconciliationContext(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc) {
- t := min(timeout, DefaultReconciliationTimeout)
-
- return context.WithTimeout(ctx, t)
-}
-
// GetChildReconciliationContext returns context with timeout for the controller's secondary client. The resulting context has a timeout equal to half of the timeout
// for the controller's main client.
func GetChildReconciliationContext(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc) {
diff --git a/pkg/extensions/cluster_test.go b/pkg/extensions/cluster_test.go
index 28a86b65268..8a2626cea9b 100644
--- a/pkg/extensions/cluster_test.go
+++ b/pkg/extensions/cluster_test.go
@@ -12,6 +12,8 @@ import (
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -39,7 +41,10 @@ var _ = Describe("Cluster", func() {
BeforeEach(func() {
fakeGardenClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.GardenScheme).Build()
- fakeSeedClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
+ objectTracker := testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())
+ fakeSeedClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithObjectTracker(objectTracker).Build()
})
Describe("#GenericTokenKubeconfigSecretNameFromCluster", func() {
diff --git a/pkg/gardenadm/staticpod/translator_test.go b/pkg/gardenadm/staticpod/translator_test.go
index 2b8868079cc..11f77f0d168 100644
--- a/pkg/gardenadm/staticpod/translator_test.go
+++ b/pkg/gardenadm/staticpod/translator_test.go
@@ -72,7 +72,6 @@ metadata:
annotations:
bar: baz
gardener.cloud/config.mirror: ` + hash + `
- creationTimestamp: null
labels:
baz: foo
static-pod: "true"
@@ -116,7 +115,6 @@ metadata:
bar: baz
foo: bar
gardener.cloud/config.mirror: ` + hash + `
- creationTimestamp: null
labels:
foo: bar
static-pod: "true"
@@ -237,7 +235,6 @@ metadata:
annotations:
bar: baz
gardener.cloud/config.mirror: ` + hash + `
- creationTimestamp: null
labels:
baz: foo
static-pod: "true"
@@ -364,7 +361,6 @@ metadata:
annotations:
bar: baz
gardener.cloud/config.mirror: ` + hash + `
- creationTimestamp: null
labels:
baz: foo
static-pod: "true"
@@ -415,7 +411,6 @@ metadata:
bar: baz
foo: bar
gardener.cloud/config.mirror: ` + hash + `
- creationTimestamp: null
labels:
foo: bar
static-pod: "true"
@@ -543,7 +538,6 @@ metadata:
annotations:
bar: baz
gardener.cloud/config.mirror: ` + hash + `
- creationTimestamp: null
labels:
baz: foo
static-pod: "true"
@@ -665,7 +659,6 @@ metadata:
annotations:
bar: baz
gardener.cloud/config.mirror: ` + hash + `
- creationTimestamp: null
labels:
baz: foo
static-pod: "true"
@@ -707,7 +700,6 @@ metadata:
bar: baz
foo: bar
gardener.cloud/config.mirror: ` + hash + `
- creationTimestamp: null
labels:
foo: bar
static-pod: "true"
@@ -826,7 +818,6 @@ metadata:
annotations:
bar: baz
gardener.cloud/config.mirror: ` + hash + `
- creationTimestamp: null
labels:
baz: foo
static-pod: "true"
diff --git a/pkg/gardenlet/apis/config/v1alpha1/validation/validation_test.go b/pkg/gardenlet/apis/config/v1alpha1/validation/validation_test.go
index fd31afcf283..f8859c619e6 100644
--- a/pkg/gardenlet/apis/config/v1alpha1/validation/validation_test.go
+++ b/pkg/gardenlet/apis/config/v1alpha1/validation/validation_test.go
@@ -286,7 +286,7 @@ var _ = Describe("GardenletConfiguration", func() {
Expect(ValidateGardenletConfiguration(cfg, nil)).To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
+ "Type": Equal(field.ErrorTypeRequired),
"Field": Equal("leaderElection.resourceNamespace"),
})),
))
diff --git a/pkg/gardenlet/controller/backupbucket/add.go b/pkg/gardenlet/controller/backupbucket/add.go
index 3d51f00a2ff..09cd858eec4 100644
--- a/pkg/gardenlet/controller/backupbucket/add.go
+++ b/pkg/gardenlet/controller/backupbucket/add.go
@@ -23,6 +23,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -53,6 +54,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster cluster.Clu
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
RateLimiter: r.RateLimiter,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(source.Kind[client.Object](
gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/backupbucket/reconciler.go b/pkg/gardenlet/controller/backupbucket/reconciler.go
index 69ecf85a866..2c1c0ca2d97 100644
--- a/pkg/gardenlet/controller/backupbucket/reconciler.go
+++ b/pkg/gardenlet/controller/backupbucket/reconciler.go
@@ -20,6 +20,7 @@ import (
"k8s.io/client-go/util/workqueue"
"k8s.io/utils/clock"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -29,6 +30,7 @@ import (
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
+ "github.com/gardener/gardener/pkg/client/kubernetes"
"github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/extensions"
gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
@@ -61,8 +63,7 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- gardenCtx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
+ gardenCtx := ctx
seedCtx, cancel := controllerutils.GetChildReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
defer cancel()
@@ -379,12 +380,16 @@ func (r *Reconciler) reconcileBackupBucketExtensionSecret(ctx context.Context, e
})
return err
case *securityv1alpha1.WorkloadIdentity:
+ gvk, err := apiutil.GVKForObject(backupBucket, kubernetes.GardenScheme)
+ if err != nil {
+ return err
+ }
s, err := workloadidentity.NewSecret(
extensionSecret.Name,
extensionSecret.Namespace,
workloadidentity.For(credentials.GetName(), credentials.GetNamespace(), credentials.Spec.TargetSystem.Type),
workloadidentity.WithProviderConfig(credentials.Spec.TargetSystem.ProviderConfig),
- workloadidentity.WithContextObject(securityv1alpha1.ContextObject{APIVersion: backupBucket.APIVersion, Kind: backupBucket.Kind, Name: backupBucket.GetName(), UID: backupBucket.GetUID()}),
+ workloadidentity.WithContextObject(securityv1alpha1.ContextObject{APIVersion: gvk.GroupVersion().String(), Kind: gvk.Kind, Name: backupBucket.GetName(), UID: backupBucket.GetUID()}),
workloadidentity.WithAnnotations(map[string]string{v1beta1constants.GardenerTimestamp: now}),
)
if err != nil {
@@ -534,10 +539,14 @@ func generateGeneratedBackupBucketSecretName(backupBucketName string) string {
}
func workloadIdentitySecretChanged(backupBucket *gardencorev1beta1.BackupBucket, secretToCompareTo *corev1.Secret, workloadIdentity *securityv1alpha1.WorkloadIdentity) (bool, error) {
+ gvk, err := apiutil.GVKForObject(backupBucket, kubernetes.GardenScheme)
+ if err != nil {
+ return false, err
+ }
opts := []workloadidentity.SecretOption{
workloadidentity.For(workloadIdentity.GetName(), workloadIdentity.GetNamespace(), workloadIdentity.Spec.TargetSystem.Type),
workloadidentity.WithProviderConfig(workloadIdentity.Spec.TargetSystem.ProviderConfig),
- workloadidentity.WithContextObject(securityv1alpha1.ContextObject{APIVersion: backupBucket.APIVersion, Kind: backupBucket.Kind, Name: backupBucket.GetName(), UID: backupBucket.GetUID()}),
+ workloadidentity.WithContextObject(securityv1alpha1.ContextObject{APIVersion: gvk.GroupVersion().String(), Kind: gvk.Kind, Name: backupBucket.GetName(), UID: backupBucket.GetUID()}),
}
if val, ok := secretToCompareTo.Annotations[v1beta1constants.GardenerTimestamp]; ok {
opts = append(opts, workloadidentity.WithAnnotations(map[string]string{v1beta1constants.GardenerTimestamp: val}))
diff --git a/pkg/gardenlet/controller/backupentry/add.go b/pkg/gardenlet/controller/backupentry/add.go
index f0f324f6600..a1d2aa01ed0 100644
--- a/pkg/gardenlet/controller/backupentry/add.go
+++ b/pkg/gardenlet/controller/backupentry/add.go
@@ -25,6 +25,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/controllerutils/mapper"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
"github.com/gardener/gardener/pkg/extensions"
@@ -58,6 +59,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster, seedCluste
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
RateLimiter: r.RateLimiter,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(source.Kind[client.Object](
gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/backupentry/reconciler.go b/pkg/gardenlet/controller/backupentry/reconciler.go
index 938ce251a33..2f7849e4eb5 100644
--- a/pkg/gardenlet/controller/backupentry/reconciler.go
+++ b/pkg/gardenlet/controller/backupentry/reconciler.go
@@ -22,6 +22,7 @@ import (
"k8s.io/utils/clock"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -31,6 +32,7 @@ import (
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
+ "github.com/gardener/gardener/pkg/client/kubernetes"
extensionsbackupentry "github.com/gardener/gardener/pkg/component/extensions/backupentry"
"github.com/gardener/gardener/pkg/controllerutils"
gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
@@ -70,8 +72,7 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- gardenCtx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
+ gardenCtx := ctx
seedCtx, cancel := controllerutils.GetChildReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
defer cancel()
@@ -672,12 +673,16 @@ func (r *Reconciler) reconcileBackupEntryExtensionSecret(ctx context.Context, ex
})
return err
case *securityv1alpha1.WorkloadIdentity:
+ gvk, err := apiutil.GVKForObject(backupEntry, kubernetes.GardenScheme)
+ if err != nil {
+ return err
+ }
s, err := workloadidentity.NewSecret(
extensionSecret.Name,
extensionSecret.Namespace,
workloadidentity.For(credentials.GetName(), credentials.GetNamespace(), credentials.Spec.TargetSystem.Type),
workloadidentity.WithProviderConfig(credentials.Spec.TargetSystem.ProviderConfig),
- workloadidentity.WithContextObject(securityv1alpha1.ContextObject{APIVersion: backupEntry.APIVersion, Kind: backupEntry.Kind, Namespace: ptr.To(backupEntry.GetNamespace()), Name: backupEntry.GetName(), UID: backupEntry.GetUID()}),
+ workloadidentity.WithContextObject(securityv1alpha1.ContextObject{APIVersion: gvk.GroupVersion().String(), Kind: gvk.Kind, Namespace: ptr.To(backupEntry.GetNamespace()), Name: backupEntry.GetName(), UID: backupEntry.GetUID()}),
workloadidentity.WithAnnotations(map[string]string{v1beta1constants.GardenerTimestamp: now}),
)
if err != nil {
@@ -743,10 +748,14 @@ func removeGardenerOperationAnnotation(ctx context.Context, c client.Client, be
}
func workloadIdentitySecretChanged(backupEntry *gardencorev1beta1.BackupEntry, secretToCompareTo *corev1.Secret, workloadIdentity *securityv1alpha1.WorkloadIdentity) (bool, error) {
+ gvk, err := apiutil.GVKForObject(backupEntry, kubernetes.GardenScheme)
+ if err != nil {
+ return false, err
+ }
opts := []workloadidentity.SecretOption{
workloadidentity.For(workloadIdentity.GetName(), workloadIdentity.GetNamespace(), workloadIdentity.Spec.TargetSystem.Type),
workloadidentity.WithProviderConfig(workloadIdentity.Spec.TargetSystem.ProviderConfig),
- workloadidentity.WithContextObject(securityv1alpha1.ContextObject{APIVersion: backupEntry.APIVersion, Kind: backupEntry.Kind, Namespace: ptr.To(backupEntry.GetNamespace()), Name: backupEntry.GetName(), UID: backupEntry.GetUID()}),
+ workloadidentity.WithContextObject(securityv1alpha1.ContextObject{APIVersion: gvk.GroupVersion().String(), Kind: gvk.Kind, Namespace: ptr.To(backupEntry.GetNamespace()), Name: backupEntry.GetName(), UID: backupEntry.GetUID()}),
}
if val, ok := secretToCompareTo.Annotations[v1beta1constants.GardenerTimestamp]; ok {
opts = append(opts, workloadidentity.WithAnnotations(map[string]string{v1beta1constants.GardenerTimestamp: val}))
diff --git a/pkg/gardenlet/controller/bastion/add.go b/pkg/gardenlet/controller/bastion/add.go
index fcd63826599..dc1247b21b7 100644
--- a/pkg/gardenlet/controller/bastion/add.go
+++ b/pkg/gardenlet/controller/bastion/add.go
@@ -23,6 +23,7 @@ import (
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
operationsv1alpha1 "github.com/gardener/gardener/pkg/apis/operations/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
"github.com/gardener/gardener/pkg/extensions"
)
@@ -48,6 +49,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster, seedCluste
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
RateLimiter: r.RateLimiter,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(source.Kind[client.Object](
gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/bastion/reconciler.go b/pkg/gardenlet/controller/bastion/reconciler.go
index f7d62a64bb2..f57bb932684 100644
--- a/pkg/gardenlet/controller/bastion/reconciler.go
+++ b/pkg/gardenlet/controller/bastion/reconciler.go
@@ -51,8 +51,7 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- gardenCtx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
+ gardenCtx := ctx
seedCtx, cancel := controllerutils.GetChildReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
defer cancel()
diff --git a/pkg/gardenlet/controller/controllerinstallation/care/add.go b/pkg/gardenlet/controller/controllerinstallation/care/add.go
index 3dfad024cac..e1153347a54 100644
--- a/pkg/gardenlet/controller/controllerinstallation/care/add.go
+++ b/pkg/gardenlet/controller/controllerinstallation/care/add.go
@@ -52,7 +52,8 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster, seedCluste
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
// if going into exponential backoff, wait at most the configured sync period
- RateLimiter: workqueue.NewTypedWithMaxWaitRateLimiter(workqueue.DefaultTypedControllerRateLimiter[reconcile.Request](), r.Config.SyncPeriod.Duration),
+ RateLimiter: workqueue.NewTypedWithMaxWaitRateLimiter(workqueue.DefaultTypedControllerRateLimiter[reconcile.Request](), r.Config.SyncPeriod.Duration),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
WatchesRawSource(source.Kind[client.Object](
gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/controllerinstallation/care/reconciler.go b/pkg/gardenlet/controller/controllerinstallation/care/reconciler.go
index 2f0a94e3ab2..f59d30cf7c1 100644
--- a/pkg/gardenlet/controller/controllerinstallation/care/reconciler.go
+++ b/pkg/gardenlet/controller/controllerinstallation/care/reconciler.go
@@ -37,8 +37,7 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- gardenCtx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
+ gardenCtx := ctx
seedCtx, cancel := controllerutils.GetChildReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
defer cancel()
diff --git a/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/add.go b/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/add.go
index fe056cbcd77..f0d87a802c5 100644
--- a/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/add.go
+++ b/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/add.go
@@ -23,6 +23,7 @@ import (
gardencorev1 "github.com/gardener/gardener/pkg/apis/core/v1"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils/oci"
)
@@ -52,6 +53,7 @@ func (r *Reconciler) AddToManager(ctx context.Context, mgr manager.Manager, gard
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.Controllers.ControllerInstallation.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(
source.Kind[client.Object](gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/reconciler.go b/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/reconciler.go
index bb7205aca39..064e471d7b8 100644
--- a/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/reconciler.go
+++ b/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/reconciler.go
@@ -84,8 +84,7 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- gardenCtx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
+ gardenCtx := ctx
seedCtx, cancel := controllerutils.GetChildReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
defer cancel()
diff --git a/pkg/gardenlet/controller/controllerinstallation/required/add.go b/pkg/gardenlet/controller/controllerinstallation/required/add.go
index 8f410b3015a..949f0e71c4b 100644
--- a/pkg/gardenlet/controller/controllerinstallation/required/add.go
+++ b/pkg/gardenlet/controller/controllerinstallation/required/add.go
@@ -58,6 +58,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster, seedCluste
controller.Options{
Reconciler: r,
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
},
)
if err != nil {
diff --git a/pkg/gardenlet/controller/controllerinstallation/required/reconciler.go b/pkg/gardenlet/controller/controllerinstallation/required/reconciler.go
index 12bfc9d0c05..4400f10b1a5 100644
--- a/pkg/gardenlet/controller/controllerinstallation/required/reconciler.go
+++ b/pkg/gardenlet/controller/controllerinstallation/required/reconciler.go
@@ -19,7 +19,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
- "github.com/gardener/gardener/pkg/controllerutils"
gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
)
@@ -40,9 +39,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
controllerInstallation := &gardencorev1beta1.ControllerInstallation{}
if err := r.GardenClient.Get(ctx, request.NamespacedName, controllerInstallation); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/gardenlet/controller/gardenlet/add.go b/pkg/gardenlet/controller/gardenlet/add.go
index d654ce8ec13..dc787185490 100644
--- a/pkg/gardenlet/controller/gardenlet/add.go
+++ b/pkg/gardenlet/controller/gardenlet/add.go
@@ -70,6 +70,7 @@ func (r *Reconciler) AddToManager(
// There can only be one Gardenlet object relevant for an instance of gardenlet, so it's enough to have one
// worker only.
MaxConcurrentReconciles: 1,
+ ReconciliationTimeout: r.Config.Controllers.Gardenlet.SyncPeriod.Duration,
}).
WatchesRawSource(source.Kind[client.Object](
gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/gardenlet/reconciler.go b/pkg/gardenlet/controller/gardenlet/reconciler.go
index 04b5864c4d2..80deacb694f 100644
--- a/pkg/gardenlet/controller/gardenlet/reconciler.go
+++ b/pkg/gardenlet/controller/gardenlet/reconciler.go
@@ -27,7 +27,6 @@ import (
"github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1/helper"
"github.com/gardener/gardener/pkg/client/kubernetes"
"github.com/gardener/gardener/pkg/controller/gardenletdeployer"
- "github.com/gardener/gardener/pkg/controllerutils"
gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
gardenletutils "github.com/gardener/gardener/pkg/utils/gardener/gardenlet"
@@ -51,9 +50,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.Controllers.Gardenlet.SyncPeriod.Duration)
- defer cancel()
-
gardenlet := &seedmanagementv1alpha1.Gardenlet{}
if err := r.GardenClient.Get(ctx, request.NamespacedName, gardenlet); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/gardenlet/controller/managedseed/add.go b/pkg/gardenlet/controller/managedseed/add.go
index 1f627ad3b0b..3c5cf7ec802 100644
--- a/pkg/gardenlet/controller/managedseed/add.go
+++ b/pkg/gardenlet/controller/managedseed/add.go
@@ -68,6 +68,7 @@ func (r *Reconciler) AddToManager(
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.Controllers.ManagedSeed.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.Controllers.ManagedSeed.SyncPeriod.Duration,
}).
WatchesRawSource(source.Kind[client.Object](
gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/managedseed/reconciler.go b/pkg/gardenlet/controller/managedseed/reconciler.go
index 9a813907fda..7786201cea7 100644
--- a/pkg/gardenlet/controller/managedseed/reconciler.go
+++ b/pkg/gardenlet/controller/managedseed/reconciler.go
@@ -54,9 +54,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.Controllers.ManagedSeed.SyncPeriod.Duration)
- defer cancel()
-
ms := &seedmanagementv1alpha1.ManagedSeed{}
if err := r.GardenClient.Get(ctx, request.NamespacedName, ms); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/gardenlet/controller/seed/care/add.go b/pkg/gardenlet/controller/seed/care/add.go
index 2490ae1fd36..2d3d8f51e78 100644
--- a/pkg/gardenlet/controller/seed/care/add.go
+++ b/pkg/gardenlet/controller/seed/care/add.go
@@ -48,7 +48,8 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster, seedCluste
WithOptions(controller.Options{
MaxConcurrentReconciles: 1,
// if going into exponential backoff, wait at most the configured sync period
- RateLimiter: workqueue.NewTypedWithMaxWaitRateLimiter(workqueue.DefaultTypedControllerRateLimiter[reconcile.Request](), r.Config.SyncPeriod.Duration),
+ RateLimiter: workqueue.NewTypedWithMaxWaitRateLimiter(workqueue.DefaultTypedControllerRateLimiter[reconcile.Request](), r.Config.SyncPeriod.Duration),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
WatchesRawSource(source.Kind[client.Object](
gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/seed/care/reconciler.go b/pkg/gardenlet/controller/seed/care/reconciler.go
index 0f800d5e3ee..4f308ab1844 100644
--- a/pkg/gardenlet/controller/seed/care/reconciler.go
+++ b/pkg/gardenlet/controller/seed/care/reconciler.go
@@ -42,11 +42,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(reconcileCtx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(reconcileCtx)
- // Timeout for all calls (e.g. status updates), give status updates a bit of headroom if health checks
- // themselves run into timeouts, so that we will still update the status with that timeout error.
- reconcileCtx, cancel := controllerutils.GetMainReconciliationContext(reconcileCtx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
seed := &gardencorev1beta1.Seed{}
if err := r.GardenClient.Get(reconcileCtx, req.NamespacedName, seed); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/gardenlet/controller/seed/lease/add.go b/pkg/gardenlet/controller/seed/lease/add.go
index 6289db46386..f29ebd7682c 100644
--- a/pkg/gardenlet/controller/seed/lease/add.go
+++ b/pkg/gardenlet/controller/seed/lease/add.go
@@ -43,6 +43,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster cluster.Clu
WithOptions(controller.Options{
MaxConcurrentReconciles: 1,
RateLimiter: workqueue.NewTypedItemExponentialFailureRateLimiter[reconcile.Request](time.Millisecond, 2*time.Second),
+ ReconciliationTimeout: time.Duration(*r.Config.LeaseResyncSeconds) * time.Second,
}).
WatchesRawSource(
source.Kind[client.Object](gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/seed/lease/reconciler.go b/pkg/gardenlet/controller/seed/lease/reconciler.go
index c6d9a0f56ad..6ed700c6063 100644
--- a/pkg/gardenlet/controller/seed/lease/reconciler.go
+++ b/pkg/gardenlet/controller/seed/lease/reconciler.go
@@ -44,9 +44,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, time.Duration(*r.Config.LeaseResyncSeconds)*time.Second)
- defer cancel()
-
seed := &gardencorev1beta1.Seed{}
if err := r.GardenClient.Get(ctx, request.NamespacedName, seed); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/gardenlet/controller/shoot/care/add.go b/pkg/gardenlet/controller/shoot/care/add.go
index ca761f4bafd..0df83805176 100644
--- a/pkg/gardenlet/controller/shoot/care/add.go
+++ b/pkg/gardenlet/controller/shoot/care/add.go
@@ -45,7 +45,8 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster cluster.Clu
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.Controllers.ShootCare.ConcurrentSyncs, 0),
// if going into exponential backoff, wait at most the configured sync period
- RateLimiter: workqueue.NewTypedWithMaxWaitRateLimiter(workqueue.DefaultTypedControllerRateLimiter[reconcile.Request](), r.Config.Controllers.ShootCare.SyncPeriod.Duration),
+ RateLimiter: workqueue.NewTypedWithMaxWaitRateLimiter(workqueue.DefaultTypedControllerRateLimiter[reconcile.Request](), r.Config.Controllers.ShootCare.SyncPeriod.Duration),
+ ReconciliationTimeout: r.Config.Controllers.ShootCare.SyncPeriod.Duration,
}).
WatchesRawSource(
source.Kind[client.Object](gardenCluster.GetCache(),
diff --git a/pkg/gardenlet/controller/shoot/care/health_test.go b/pkg/gardenlet/controller/shoot/care/health_test.go
index 16107d932b0..a91e6cb236b 100644
--- a/pkg/gardenlet/controller/shoot/care/health_test.go
+++ b/pkg/gardenlet/controller/shoot/care/health_test.go
@@ -22,6 +22,8 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
testclock "k8s.io/utils/clock/testing"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -72,7 +74,10 @@ var _ = Describe("health check", func() {
)
BeforeEach(func() {
- fakeClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
+ objectTracker := testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())
+ fakeClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithObjectTracker(objectTracker).Build()
fakeClock = testclock.NewFakeClock(time.Now())
condition = gardencorev1beta1.Condition{
Type: "test",
diff --git a/pkg/gardenlet/controller/shoot/care/reconciler.go b/pkg/gardenlet/controller/shoot/care/reconciler.go
index 21e3329a660..8e06c0befa0 100644
--- a/pkg/gardenlet/controller/shoot/care/reconciler.go
+++ b/pkg/gardenlet/controller/shoot/care/reconciler.go
@@ -65,11 +65,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- // Timeout for all calls (e.g. status updates), give status updates a bit of headroom if health checks
- // themselves run into timeouts, so that we will still update the status with that timeout error.
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.Controllers.ShootCare.SyncPeriod.Duration)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.GardenClient.Get(ctx, req.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/gardenlet/controller/shoot/shoot/cleaner_test.go b/pkg/gardenlet/controller/shoot/shoot/cleaner_test.go
index d0b24b8da5d..0a3a1e57790 100644
--- a/pkg/gardenlet/controller/shoot/shoot/cleaner_test.go
+++ b/pkg/gardenlet/controller/shoot/shoot/cleaner_test.go
@@ -15,6 +15,8 @@ import (
. "github.com/onsi/gomega/gstruct"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -63,7 +65,10 @@ var _ = Describe("cleaner", func() {
log = logr.Discard()
- seedClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
+ objectTracker := testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())
+ seedClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithObjectTracker(objectTracker).Build()
gardenClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.GardenScheme).Build()
cleaner = NewCleaner(log, seedClient, gardenClient, namespace)
diff --git a/pkg/gardenlet/controller/shoot/state/add.go b/pkg/gardenlet/controller/shoot/state/add.go
index c2e5f231993..fc2175e998c 100644
--- a/pkg/gardenlet/controller/shoot/state/add.go
+++ b/pkg/gardenlet/controller/shoot/state/add.go
@@ -18,6 +18,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -38,7 +39,10 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster, seedCluste
return builder.
ControllerManagedBy(mgr).
Named(ControllerName).
- WithOptions(controller.Options{MaxConcurrentReconciles: *r.Config.ConcurrentSyncs}).
+ WithOptions(controller.Options{
+ MaxConcurrentReconciles: *r.Config.ConcurrentSyncs,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
+ }).
WatchesRawSource(
source.Kind[client.Object](gardenCluster.GetCache(),
&gardencorev1beta1.Shoot{},
diff --git a/pkg/gardenlet/controller/shoot/state/reconciler.go b/pkg/gardenlet/controller/shoot/state/reconciler.go
index 27383cb69d6..e888cf66181 100644
--- a/pkg/gardenlet/controller/shoot/state/reconciler.go
+++ b/pkg/gardenlet/controller/shoot/state/reconciler.go
@@ -18,7 +18,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
- "github.com/gardener/gardener/pkg/controllerutils"
gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/utils"
"github.com/gardener/gardener/pkg/utils/gardener/shootstate"
@@ -46,9 +45,6 @@ var (
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.GardenClient.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/gardenlet/controller/shoot/status/add.go b/pkg/gardenlet/controller/shoot/status/add.go
index 51550ec6b88..a31ac96087b 100644
--- a/pkg/gardenlet/controller/shoot/status/add.go
+++ b/pkg/gardenlet/controller/shoot/status/add.go
@@ -22,6 +22,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/extensions"
)
@@ -40,7 +41,10 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster, seedCluste
return builder.
ControllerManagedBy(mgr).
Named(ControllerName).
- WithOptions(controller.Options{MaxConcurrentReconciles: *r.Config.ConcurrentSyncs}).
+ WithOptions(controller.Options{
+ MaxConcurrentReconciles: *r.Config.ConcurrentSyncs,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
+ }).
WatchesRawSource(source.Kind[client.Object](
seedCluster.GetCache(),
&extensionsv1alpha1.Worker{},
diff --git a/pkg/gardenlet/controller/shoot/status/reconciler.go b/pkg/gardenlet/controller/shoot/status/reconciler.go
index aca9e2f47d4..14b7a5ca5a7 100644
--- a/pkg/gardenlet/controller/shoot/status/reconciler.go
+++ b/pkg/gardenlet/controller/shoot/status/reconciler.go
@@ -21,7 +21,6 @@ import (
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
@@ -39,9 +38,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.GardenClient.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/gardenlet/controller/tokenrequestor/workloadidentity/add.go b/pkg/gardenlet/controller/tokenrequestor/workloadidentity/add.go
index a2177a2293f..7fbca71ab79 100644
--- a/pkg/gardenlet/controller/tokenrequestor/workloadidentity/add.go
+++ b/pkg/gardenlet/controller/tokenrequestor/workloadidentity/add.go
@@ -20,6 +20,7 @@ import (
securityv1alpha1constants "github.com/gardener/gardener/pkg/apis/security/v1alpha1/constants"
securityclientset "github.com/gardener/gardener/pkg/client/security/clientset/versioned"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of the controller.
@@ -55,6 +56,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, sourceCluster, targetClus
For(&corev1.Secret{}, builder.WithPredicates(r.SecretPredicate())).
WithOptions(controller.Options{
MaxConcurrentReconciles: r.ConcurrentSyncs,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/gardenlet/controller/tokenrequestor/workloadidentity/reconciler.go b/pkg/gardenlet/controller/tokenrequestor/workloadidentity/reconciler.go
index c1b00df970a..118d658ed7b 100644
--- a/pkg/gardenlet/controller/tokenrequestor/workloadidentity/reconciler.go
+++ b/pkg/gardenlet/controller/tokenrequestor/workloadidentity/reconciler.go
@@ -23,7 +23,6 @@ import (
securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
securityv1alpha1constants "github.com/gardener/gardener/pkg/apis/security/v1alpha1/constants"
securityclientset "github.com/gardener/gardener/pkg/client/security/clientset/versioned"
- "github.com/gardener/gardener/pkg/controllerutils"
)
const (
@@ -42,11 +41,8 @@ type Reconciler struct {
}
// Reconcile requests and populates tokens.
-func (r *Reconciler) Reconcile(reconcileCtx context.Context, req reconcile.Request) (reconcile.Result, error) {
- log := logf.FromContext(reconcileCtx)
-
- ctx, cancel := controllerutils.GetMainReconciliationContext(reconcileCtx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
+func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
+ log := logf.FromContext(ctx)
secret := &corev1.Secret{}
if err := r.SeedClient.Get(ctx, req.NamespacedName, secret); err != nil {
diff --git a/pkg/gardenlet/operation/botanist/kubeapiserver_test.go b/pkg/gardenlet/operation/botanist/kubeapiserver_test.go
index 76440f5fcf7..e8c45a9fc64 100644
--- a/pkg/gardenlet/operation/botanist/kubeapiserver_test.go
+++ b/pkg/gardenlet/operation/botanist/kubeapiserver_test.go
@@ -489,7 +489,6 @@ contexts:
name: authorization-webhook
current-context: authorization-webhook
kind: Config
-preferences: {}
users:
- name: authorization-webhook
user: {}
diff --git a/pkg/gardenlet/operation/botanist/kubeproxy_test.go b/pkg/gardenlet/operation/botanist/kubeproxy_test.go
index cd171669aad..2156499b6e9 100644
--- a/pkg/gardenlet/operation/botanist/kubeproxy_test.go
+++ b/pkg/gardenlet/operation/botanist/kubeproxy_test.go
@@ -153,7 +153,6 @@ contexts:
name: ` + namespace + `
current-context: ` + namespace + `
kind: Config
-preferences: {}
users:
- name: ` + namespace + `
user:
diff --git a/pkg/gardenlet/operation/botanist/machinecontrollermanager_test.go b/pkg/gardenlet/operation/botanist/machinecontrollermanager_test.go
index fb9f17ba939..dc3366c0c01 100644
--- a/pkg/gardenlet/operation/botanist/machinecontrollermanager_test.go
+++ b/pkg/gardenlet/operation/botanist/machinecontrollermanager_test.go
@@ -18,6 +18,8 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -54,7 +56,10 @@ var _ = Describe("MachineControllerManager", func() {
ctrl = gomock.NewController(GinkgoT())
kubernetesClient = kubernetesmock.NewMockInterface(ctrl)
- fakeClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
+ objectTracker := testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())
+ fakeClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithObjectTracker(objectTracker).Build()
fakeSecretsManager = fakesecretsmanager.New(fakeClient, namespace)
shoot = &gardencorev1beta1.Shoot{Spec: gardencorev1beta1.ShootSpec{Kubernetes: gardencorev1beta1.Kubernetes{Version: "1.31.1"}}}
diff --git a/pkg/gardenlet/operation/botanist/migration_test.go b/pkg/gardenlet/operation/botanist/migration_test.go
index 4739a0b6a0d..b6ec944e9d2 100644
--- a/pkg/gardenlet/operation/botanist/migration_test.go
+++ b/pkg/gardenlet/operation/botanist/migration_test.go
@@ -17,6 +17,8 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -67,7 +69,10 @@ var _ = Describe("migration", func() {
operatingSystemConfig = mockoperatingsystemconfig.NewMockInterface(ctrl)
worker = mockworker.NewMockInterface(ctrl)
- fakeClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
+ objectTracker := testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())
+ fakeClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithObjectTracker(objectTracker).Build()
fakeKubernetesInterface = fakekubernetes.NewClientSetBuilder().WithClient(fakeClient).Build()
botanist = &Botanist{Operation: &operation.Operation{
diff --git a/pkg/gardenlet/operation/botanist/secrets.go b/pkg/gardenlet/operation/botanist/secrets.go
index 7010338494f..925fa53702d 100644
--- a/pkg/gardenlet/operation/botanist/secrets.go
+++ b/pkg/gardenlet/operation/botanist/secrets.go
@@ -15,12 +15,14 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
+ "github.com/gardener/gardener/pkg/client/kubernetes"
kubeapiserver "github.com/gardener/gardener/pkg/component/kubernetes/apiserver"
"github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils/flow"
@@ -523,9 +525,13 @@ func (b *Botanist) DeployCloudProviderSecret(ctx context.Context) error {
switch credentials := b.Shoot.Credentials.(type) {
case *securityv1alpha1.WorkloadIdentity:
shootInfo := b.Shoot.GetInfo()
+ gvk, err := apiutil.GVKForObject(shootInfo, kubernetes.GardenScheme)
+ if err != nil {
+ return err
+ }
shootMeta := securityv1alpha1.ContextObject{
- APIVersion: shootInfo.GroupVersionKind().GroupVersion().String(),
- Kind: shootInfo.Kind,
+ APIVersion: gvk.GroupVersion().String(),
+ Kind: gvk.Kind,
Namespace: ptr.To(shootInfo.Namespace),
Name: shootInfo.Name,
UID: shootInfo.UID,
diff --git a/pkg/nodeagent/bootstrappers/kubelet_bootstrap_kubeconfig_test.go b/pkg/nodeagent/bootstrappers/kubelet_bootstrap_kubeconfig_test.go
index bfe33c01fe5..52dc0390296 100644
--- a/pkg/nodeagent/bootstrappers/kubelet_bootstrap_kubeconfig_test.go
+++ b/pkg/nodeagent/bootstrappers/kubelet_bootstrap_kubeconfig_test.go
@@ -100,7 +100,6 @@ contexts:
name: kubelet-bootstrap
current-context: kubelet-bootstrap
kind: Config
-preferences: {}
users:
- name: kubelet-bootstrap
user:
diff --git a/pkg/nodeagent/controller/node/add.go b/pkg/nodeagent/controller/node/add.go
index 1a285080228..c7dabde8734 100644
--- a/pkg/nodeagent/controller/node/add.go
+++ b/pkg/nodeagent/controller/node/add.go
@@ -12,6 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/predicate"
+ "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/nodeagent/dbus"
)
@@ -36,7 +37,10 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, nodePredicate predicate.P
ControllerManagedBy(mgr).
Named(ControllerName).
For(&corev1.Node{}, builder.WithPredicates(r.NodePredicate(), nodePredicate)).
- WithOptions(controller.Options{MaxConcurrentReconciles: 1}).
+ WithOptions(controller.Options{
+ MaxConcurrentReconciles: 1,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
+ }).
Complete(r)
}
diff --git a/pkg/nodeagent/controller/node/reconciler.go b/pkg/nodeagent/controller/node/reconciler.go
index aaf87a3cb20..36eaa11627d 100644
--- a/pkg/nodeagent/controller/node/reconciler.go
+++ b/pkg/nodeagent/controller/node/reconciler.go
@@ -17,7 +17,6 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
- "github.com/gardener/gardener/pkg/controllerutils"
nodeagentconfigv1alpha1 "github.com/gardener/gardener/pkg/nodeagent/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/nodeagent/dbus"
)
@@ -35,9 +34,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
node := &corev1.Node{}
if err := r.Client.Get(ctx, request.NamespacedName, node); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/nodeagent/controller/operatingsystemconfig/add.go b/pkg/nodeagent/controller/operatingsystemconfig/add.go
index c0b530ce358..c33e575562d 100644
--- a/pkg/nodeagent/controller/operatingsystemconfig/add.go
+++ b/pkg/nodeagent/controller/operatingsystemconfig/add.go
@@ -26,6 +26,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
nodeagentconfigv1alpha1 "github.com/gardener/gardener/pkg/nodeagent/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/nodeagent/dbus"
@@ -66,7 +67,10 @@ func (r *Reconciler) AddToManager(ctx context.Context, mgr manager.Manager) erro
handler.EnqueueRequestsFromMapFunc(r.NodeToSecretMapper()),
builder.WithPredicates(r.NodeReadyForUpdate()),
).
- WithOptions(controller.Options{MaxConcurrentReconciles: 1}).
+ WithOptions(controller.Options{
+ MaxConcurrentReconciles: 1,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
+ }).
Complete(r)
}
diff --git a/pkg/nodeagent/controller/operatingsystemconfig/reconciler.go b/pkg/nodeagent/controller/operatingsystemconfig/reconciler.go
index 6a314882b56..63d68b18e05 100644
--- a/pkg/nodeagent/controller/operatingsystemconfig/reconciler.go
+++ b/pkg/nodeagent/controller/operatingsystemconfig/reconciler.go
@@ -46,7 +46,6 @@ import (
extensionsv1alpha1helper "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1/helper"
"github.com/gardener/gardener/pkg/client/kubernetes"
kubeletcomponent "github.com/gardener/gardener/pkg/component/extensions/operatingsystemconfig/original/components/kubelet"
- "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/nodeagent"
nodeagentconfigv1alpha1 "github.com/gardener/gardener/pkg/nodeagent/apis/config/v1alpha1"
healthcheckcontroller "github.com/gardener/gardener/pkg/nodeagent/controller/healthcheck"
@@ -120,11 +119,8 @@ type Reconciler struct {
// Reconcile decodes the OperatingSystemConfig resources from secrets and applies the systemd units and files to the
// node.
-func (r *Reconciler) Reconcile(reconcileCtx context.Context, request reconcile.Request) (reconcile.Result, error) {
- log := logf.FromContext(reconcileCtx)
-
- ctx, cancel := controllerutils.GetMainReconciliationContext(reconcileCtx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
+func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
+ log := logf.FromContext(ctx)
secret := &corev1.Secret{}
if err := r.Client.Get(ctx, request.NamespacedName, secret); err != nil {
@@ -186,7 +182,8 @@ func (r *Reconciler) Reconcile(reconcileCtx context.Context, request reconcile.R
if isInPlaceUpdate(oscChanges) {
// In case of in-place update, we use retries for certain cases like OS update with higher timeouts,
// so we need to overwrite the context to use a longer timeout.
- ctx, cancel = context.WithTimeout(reconcileCtx, 10*time.Minute)
+ var cancel context.CancelFunc
+ ctx, cancel = context.WithTimeout(ctx, 10*time.Minute)
defer cancel()
if !nodeHasInPlaceUpdateConditionWithReasonReadyForUpdate(node.Status.Conditions) {
diff --git a/pkg/nodeagent/controller/operatingsystemconfig/reconciler_test.go b/pkg/nodeagent/controller/operatingsystemconfig/reconciler_test.go
index a2df0132da0..06e7e209de4 100644
--- a/pkg/nodeagent/controller/operatingsystemconfig/reconciler_test.go
+++ b/pkg/nodeagent/controller/operatingsystemconfig/reconciler_test.go
@@ -107,7 +107,6 @@ contexts:
name: test-context
current-context: test-context
kind: Config
-preferences: {}
`
kubeletCertPath = filepath.Join(kubeletcomponent.PathKubeletDirectory, "pki", "kubelet-client-current.pem")
@@ -751,7 +750,6 @@ contexts:
name: test-context
current-context: test-context
kind: Config
-preferences: {}
users:
- name: default-auth
user:
diff --git a/pkg/nodeagent/controller/token/add.go b/pkg/nodeagent/controller/token/add.go
index 184d6f27838..6a8c86a5174 100644
--- a/pkg/nodeagent/controller/token/add.go
+++ b/pkg/nodeagent/controller/token/add.go
@@ -19,6 +19,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/source"
+
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of this controller.
@@ -53,7 +55,10 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, channel <-chan event.Type
WatchesRawSource(
source.TypedChannel(channel, r.EventHandler()),
).
- WithOptions(controller.Options{MaxConcurrentReconciles: len(r.Config.SyncConfigs)}).
+ WithOptions(controller.Options{
+ MaxConcurrentReconciles: len(r.Config.SyncConfigs),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
+ }).
Complete(r)
}
diff --git a/pkg/nodeagent/controller/token/reconciler.go b/pkg/nodeagent/controller/token/reconciler.go
index 6aeed183350..88dc2c58681 100644
--- a/pkg/nodeagent/controller/token/reconciler.go
+++ b/pkg/nodeagent/controller/token/reconciler.go
@@ -18,7 +18,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
nodeagentconfigv1alpha1 "github.com/gardener/gardener/pkg/nodeagent/apis/config/v1alpha1"
)
@@ -35,9 +34,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
secret := &corev1.Secret{}
if err := r.APIReader.Get(ctx, request.NamespacedName, secret); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/operator/apis/config/v1alpha1/validation/validation_test.go b/pkg/operator/apis/config/v1alpha1/validation/validation_test.go
index ea3c9c1fcca..20fb09e89a5 100644
--- a/pkg/operator/apis/config/v1alpha1/validation/validation_test.go
+++ b/pkg/operator/apis/config/v1alpha1/validation/validation_test.go
@@ -129,7 +129,7 @@ var _ = Describe("#ValidateOperatorConfiguration", func() {
Expect(ValidateOperatorConfiguration(conf)).To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
+ "Type": Equal(field.ErrorTypeRequired),
"Field": Equal("leaderElection.resourceNamespace"),
})),
))
diff --git a/pkg/operator/controller/extension/care/add.go b/pkg/operator/controller/extension/care/add.go
index b60a2ff99a2..db70167b654 100644
--- a/pkg/operator/controller/extension/care/add.go
+++ b/pkg/operator/controller/extension/care/add.go
@@ -60,6 +60,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, virtualCluster cluster.Cl
workqueue.DefaultTypedControllerRateLimiter[reconcile.Request](),
r.Config.Controllers.ExtensionCare.SyncPeriod.Duration,
),
+ ReconciliationTimeout: r.Config.Controllers.ExtensionCare.SyncPeriod.Duration,
}).
Watches(
&operatorv1alpha1.Extension{},
diff --git a/pkg/operator/controller/extension/care/reconciler.go b/pkg/operator/controller/extension/care/reconciler.go
index 2835aff2b7c..3331e71123d 100644
--- a/pkg/operator/controller/extension/care/reconciler.go
+++ b/pkg/operator/controller/extension/care/reconciler.go
@@ -36,11 +36,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(reconcileCtx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(reconcileCtx)
- // Timeout for all calls (e.g. status updates), give status updates a bit of headroom if health checks
- // themselves run into timeouts, so that we will still update the status with that timeout error.
- reconcileCtx, cancel := controllerutils.GetMainReconciliationContext(reconcileCtx, r.Config.Controllers.ExtensionCare.SyncPeriod.Duration)
- defer cancel()
-
extension := &operatorv1alpha1.Extension{}
if err := r.RuntimeClient.Get(reconcileCtx, request.NamespacedName, extension); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/operator/controller/extension/extension/add.go b/pkg/operator/controller/extension/extension/add.go
index f1837c64b0a..02c226cee60 100644
--- a/pkg/operator/controller/extension/extension/add.go
+++ b/pkg/operator/controller/extension/extension/add.go
@@ -25,6 +25,7 @@ import (
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1"
"github.com/gardener/gardener/pkg/client/kubernetes"
+ "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/controllerutils/mapper"
"github.com/gardener/gardener/pkg/operator/controller/extension/extension/admission"
"github.com/gardener/gardener/pkg/operator/controller/extension/extension/controllerregistration"
@@ -91,6 +92,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
))).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.Controllers.Extension.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Watches(
&operatorv1alpha1.Garden{},
diff --git a/pkg/operator/controller/extension/extension/reconciler_delete.go b/pkg/operator/controller/extension/extension/reconciler_delete.go
index cf85bb96fd2..fa853013281 100644
--- a/pkg/operator/controller/extension/extension/reconciler_delete.go
+++ b/pkg/operator/controller/extension/extension/reconciler_delete.go
@@ -16,7 +16,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
"github.com/gardener/gardener/pkg/utils/flow"
"github.com/gardener/gardener/pkg/utils/gardener/operator"
)
@@ -29,9 +28,6 @@ func (r *Reconciler) delete(
reconcile.Result,
error,
) {
- deleteCtx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
var (
reconcileResult reconcile.Result
g = flow.NewGraph("Extension deletion")
@@ -62,7 +58,7 @@ func (r *Reconciler) delete(
conditions := NewConditions(r.Clock, extension.Status)
- if err := g.Compile().Run(deleteCtx, flow.Opts{
+ if err := g.Compile().Run(ctx, flow.Opts{
Log: log,
}); err != nil {
conditions.installed = v1beta1helper.UpdatedConditionWithClock(r.Clock, conditions.installed, gardencorev1beta1.ConditionFalse, ReasonDeleteFailed, err.Error())
diff --git a/pkg/operator/controller/extension/extension/reconciler_reconcile.go b/pkg/operator/controller/extension/extension/reconciler_reconcile.go
index 973ce53ce11..931c3269b62 100644
--- a/pkg/operator/controller/extension/extension/reconciler_reconcile.go
+++ b/pkg/operator/controller/extension/extension/reconciler_reconcile.go
@@ -49,12 +49,9 @@ func (r *Reconciler) reconcile(
return reconcile.Result{}, r.updateExtensionStatus(ctx, log, extension, conditions)
}
- reconcileCtx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
if !controllerutil.ContainsFinalizer(extension, operatorv1alpha1.FinalizerName) {
log.Info("Adding finalizer")
- if err := controllerutils.AddFinalizers(reconcileCtx, r.RuntimeClientSet.Client(), extension, operatorv1alpha1.FinalizerName); err != nil {
+ if err := controllerutils.AddFinalizers(ctx, r.RuntimeClientSet.Client(), extension, operatorv1alpha1.FinalizerName); err != nil {
return reconcile.Result{}, fmt.Errorf("failed to add finalizer: %w", err)
}
}
@@ -120,7 +117,7 @@ func (r *Reconciler) reconcile(
})
)
- if err := g.Compile().Run(reconcileCtx, flow.Opts{
+ if err := g.Compile().Run(ctx, flow.Opts{
Log: log,
}); err != nil {
conditions.installed = v1beta1helper.UpdatedConditionWithClock(r.Clock, conditions.installed, gardencorev1beta1.ConditionFalse, ReasonReconcileFailed, err.Error())
diff --git a/pkg/operator/controller/extension/required/runtime/add.go b/pkg/operator/controller/extension/required/runtime/add.go
index 7c4507f12c2..8ffd6218dd2 100644
--- a/pkg/operator/controller/extension/required/runtime/add.go
+++ b/pkg/operator/controller/extension/required/runtime/add.go
@@ -80,6 +80,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Build(r)
if err != nil {
diff --git a/pkg/operator/controller/extension/required/runtime/reconciler.go b/pkg/operator/controller/extension/required/runtime/reconciler.go
index 81c80a208e8..267fed125bb 100644
--- a/pkg/operator/controller/extension/required/runtime/reconciler.go
+++ b/pkg/operator/controller/extension/required/runtime/reconciler.go
@@ -22,7 +22,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
operatorconfigv1alpha1 "github.com/gardener/gardener/pkg/operator/apis/config/v1alpha1"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
"github.com/gardener/gardener/pkg/utils/gardener/operator"
@@ -45,9 +44,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
for _, ext := range runtimeClusterExtensions {
r.Lock.RLock()
_, kindProcessed := r.KindToRequiredTypes[ext.objectKind]
diff --git a/pkg/operator/controller/extension/required/virtual/add.go b/pkg/operator/controller/extension/required/virtual/add.go
index a9b5e75efe8..8c153b15d2b 100644
--- a/pkg/operator/controller/extension/required/virtual/add.go
+++ b/pkg/operator/controller/extension/required/virtual/add.go
@@ -20,6 +20,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
"github.com/gardener/gardener/pkg/operator/mapper"
)
@@ -42,6 +43,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, virtualCluster cluster.Cl
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
For(&operatorv1alpha1.Extension{}, builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create))).
WatchesRawSource(
diff --git a/pkg/operator/controller/extension/required/virtual/reconciler.go b/pkg/operator/controller/extension/required/virtual/reconciler.go
index bb44c79de1b..69b9619edc2 100644
--- a/pkg/operator/controller/extension/required/virtual/reconciler.go
+++ b/pkg/operator/controller/extension/required/virtual/reconciler.go
@@ -19,7 +19,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
operatorconfigv1alpha1 "github.com/gardener/gardener/pkg/operator/apis/config/v1alpha1"
)
@@ -38,9 +37,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
extension := &operatorv1alpha1.Extension{}
if err := r.RuntimeClient.Get(ctx, request.NamespacedName, extension); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/operator/controller/garden/care/add.go b/pkg/operator/controller/garden/care/add.go
index 155e650fa56..1a9cc22edf8 100644
--- a/pkg/operator/controller/garden/care/add.go
+++ b/pkg/operator/controller/garden/care/add.go
@@ -58,6 +58,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, gardenClientMap clientmap
workqueue.DefaultTypedControllerRateLimiter[reconcile.Request](),
r.Config.Controllers.GardenCare.SyncPeriod.Duration,
),
+ ReconciliationTimeout: r.Config.Controllers.GardenCare.SyncPeriod.Duration,
}).
Watches(
&operatorv1alpha1.Garden{},
diff --git a/pkg/operator/controller/garden/care/reconciler.go b/pkg/operator/controller/garden/care/reconciler.go
index 4e37667d79e..37d5f206d59 100644
--- a/pkg/operator/controller/garden/care/reconciler.go
+++ b/pkg/operator/controller/garden/care/reconciler.go
@@ -46,11 +46,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(reconcileCtx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(reconcileCtx)
- // Timeout for all calls (e.g. status updates), give status updates a bit of headroom if health checks
- // themselves run into timeouts, so that we will still update the status with that timeout error.
- reconcileCtx, cancel := controllerutils.GetMainReconciliationContext(reconcileCtx, r.Config.Controllers.GardenCare.SyncPeriod.Duration)
- defer cancel()
-
garden := &operatorv1alpha1.Garden{}
if err := r.RuntimeClient.Get(reconcileCtx, req.NamespacedName, garden); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/operator/controller/gardenlet/add.go b/pkg/operator/controller/gardenlet/add.go
index 1881cf61800..c03be1c5c20 100644
--- a/pkg/operator/controller/gardenlet/add.go
+++ b/pkg/operator/controller/gardenlet/add.go
@@ -24,6 +24,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
gardenletutils "github.com/gardener/gardener/pkg/utils/gardener/gardenlet"
"github.com/gardener/gardener/pkg/utils/oci"
@@ -67,6 +68,7 @@ func (r *Reconciler) AddToManager(ctx context.Context, mgr manager.Manager, virt
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: pointer.IntDeref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(source.Kind[client.Object](virtualCluster.GetCache(), &seedmanagementv1alpha1.Gardenlet{},
&handler.EnqueueRequestForObject{},
diff --git a/pkg/operator/controller/gardenlet/reconciler.go b/pkg/operator/controller/gardenlet/reconciler.go
index 3f2e86cf85b..d9312e5b4ec 100644
--- a/pkg/operator/controller/gardenlet/reconciler.go
+++ b/pkg/operator/controller/gardenlet/reconciler.go
@@ -28,7 +28,6 @@ import (
"github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1/helper"
"github.com/gardener/gardener/pkg/client/kubernetes"
"github.com/gardener/gardener/pkg/controller/gardenletdeployer"
- "github.com/gardener/gardener/pkg/controllerutils"
operatorconfigv1alpha1 "github.com/gardener/gardener/pkg/operator/apis/config/v1alpha1"
gardenletutils "github.com/gardener/gardener/pkg/utils/gardener/gardenlet"
kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
@@ -57,9 +56,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
gardenlet := &seedmanagementv1alpha1.Gardenlet{}
if err := r.VirtualClient.Get(ctx, request.NamespacedName, gardenlet); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/resourcemanager/apis/config/v1alpha1/validation/validation_test.go b/pkg/resourcemanager/apis/config/v1alpha1/validation/validation_test.go
index 355fb1fe3bf..8a43f7f2c7e 100644
--- a/pkg/resourcemanager/apis/config/v1alpha1/validation/validation_test.go
+++ b/pkg/resourcemanager/apis/config/v1alpha1/validation/validation_test.go
@@ -140,7 +140,7 @@ var _ = Describe("Validation", func() {
Expect(ValidateResourceManagerConfiguration(conf)).To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
+ "Type": Equal(field.ErrorTypeRequired),
"Field": Equal("leaderElection.resourceNamespace"),
})),
))
diff --git a/pkg/resourcemanager/controller/csrapprover/add.go b/pkg/resourcemanager/controller/csrapprover/add.go
index 0f26cc0554f..684e591ae23 100644
--- a/pkg/resourcemanager/controller/csrapprover/add.go
+++ b/pkg/resourcemanager/controller/csrapprover/add.go
@@ -16,6 +16,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/source"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -36,6 +37,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, sourceCluster, targetClus
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(
source.Kind[client.Object](targetCluster.GetCache(),
diff --git a/pkg/resourcemanager/controller/csrapprover/reconciler.go b/pkg/resourcemanager/controller/csrapprover/reconciler.go
index 755fdd05db8..ff789560783 100644
--- a/pkg/resourcemanager/controller/csrapprover/reconciler.go
+++ b/pkg/resourcemanager/controller/csrapprover/reconciler.go
@@ -26,7 +26,6 @@ import (
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
"github.com/gardener/gardener/pkg/client/kubernetes"
- "github.com/gardener/gardener/pkg/controllerutils"
resourcemanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/resourcemanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/utils"
)
@@ -51,9 +50,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
csr := &certificatesv1.CertificateSigningRequest{}
if err := r.TargetClient.Get(ctx, request.NamespacedName, csr); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/resourcemanager/controller/garbagecollector/add.go b/pkg/resourcemanager/controller/garbagecollector/add.go
index 55078ea5851..a881b6b8d12 100644
--- a/pkg/resourcemanager/controller/garbagecollector/add.go
+++ b/pkg/resourcemanager/controller/garbagecollector/add.go
@@ -33,6 +33,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, targetCluster cluster.Clu
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: 1,
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
WatchesRawSource(controllerutils.EnqueueOnce).
Complete(r)
diff --git a/pkg/resourcemanager/controller/garbagecollector/reconciler.go b/pkg/resourcemanager/controller/garbagecollector/reconciler.go
index ee9a39eca09..005ff64243d 100644
--- a/pkg/resourcemanager/controller/garbagecollector/reconciler.go
+++ b/pkg/resourcemanager/controller/garbagecollector/reconciler.go
@@ -26,7 +26,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
- "github.com/gardener/gardener/pkg/controllerutils"
resourcemanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/resourcemanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/resourcemanager/controller/garbagecollector/references"
errorsutils "github.com/gardener/gardener/pkg/utils/errors"
@@ -41,11 +40,8 @@ type Reconciler struct {
}
// Reconcile performs the main reconciliation logic.
-func (r *Reconciler) Reconcile(reconcileCtx context.Context, _ reconcile.Request) (reconcile.Result, error) {
- log := logf.FromContext(reconcileCtx)
-
- ctx, cancel := controllerutils.GetMainReconciliationContext(reconcileCtx, r.Config.SyncPeriod.Duration)
- defer cancel()
+func (r *Reconciler) Reconcile(ctx context.Context, _ reconcile.Request) (reconcile.Result, error) {
+ log := logf.FromContext(ctx)
log.Info("Starting garbage collection")
defer log.Info("Garbage collection finished")
diff --git a/pkg/resourcemanager/controller/health/health/add.go b/pkg/resourcemanager/controller/health/health/add.go
index 99c93f7cd02..3f3ebb87749 100644
--- a/pkg/resourcemanager/controller/health/health/add.go
+++ b/pkg/resourcemanager/controller/health/health/add.go
@@ -55,6 +55,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, sourceCluster, targetClus
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
Watches(
&resourcesv1alpha1.ManagedResource{},
diff --git a/pkg/resourcemanager/controller/health/health/reconciler.go b/pkg/resourcemanager/controller/health/health/reconciler.go
index 55cfbf45a1c..3ace7860199 100644
--- a/pkg/resourcemanager/controller/health/health/reconciler.go
+++ b/pkg/resourcemanager/controller/health/health/reconciler.go
@@ -47,12 +47,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- // timeout for all calls (e.g. status updates), give status updates a bit of headroom if health checks
- // themselves run into timeouts, so that we will still update the status with that timeout error
- var cancel context.CancelFunc
- ctx, cancel = controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
mr := &resourcesv1alpha1.ManagedResource{}
if err := r.SourceClient.Get(ctx, req.NamespacedName, mr); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/resourcemanager/controller/health/progressing/add.go b/pkg/resourcemanager/controller/health/progressing/add.go
index d9f9f2497ec..0d52d7559e7 100644
--- a/pkg/resourcemanager/controller/health/progressing/add.go
+++ b/pkg/resourcemanager/controller/health/progressing/add.go
@@ -65,6 +65,7 @@ func (r *Reconciler) AddToManager(ctx context.Context, mgr manager.Manager, sour
)).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
Build(r)
if err != nil {
diff --git a/pkg/resourcemanager/controller/health/progressing/reconciler.go b/pkg/resourcemanager/controller/health/progressing/reconciler.go
index 2cca0888961..fb22728f3f0 100644
--- a/pkg/resourcemanager/controller/health/progressing/reconciler.go
+++ b/pkg/resourcemanager/controller/health/progressing/reconciler.go
@@ -44,12 +44,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- // timeout for all calls (e.g. status updates), give status updates a bit of headroom if checks
- // themselves run into timeouts, so that we will still update the status with that timeout error
- var cancel context.CancelFunc
- ctx, cancel = controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
mr := &resourcesv1alpha1.ManagedResource{}
if err := r.SourceClient.Get(ctx, req.NamespacedName, mr); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/resourcemanager/controller/managedresource/add.go b/pkg/resourcemanager/controller/managedresource/add.go
index fe41a3bbc94..175176a7e83 100644
--- a/pkg/resourcemanager/controller/managedresource/add.go
+++ b/pkg/resourcemanager/controller/managedresource/add.go
@@ -56,6 +56,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, sourceCluster, targetClus
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
}).
For(&resourcesv1alpha1.ManagedResource{}, builder.WithPredicates(
r.ClassFilter,
diff --git a/pkg/resourcemanager/controller/managedresource/reconciler.go b/pkg/resourcemanager/controller/managedresource/reconciler.go
index 1b54a43cdc9..c3d61bae472 100644
--- a/pkg/resourcemanager/controller/managedresource/reconciler.go
+++ b/pkg/resourcemanager/controller/managedresource/reconciler.go
@@ -151,15 +151,12 @@ func (r *Reconciler) reconcile(ctx context.Context, log logr.Logger, mr *resourc
forceOverwriteAnnotations = *v
}
- reconcileCtx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
// Initialize condition based on the current status.
conditionResourcesApplied := v1beta1helper.GetOrInitConditionWithClock(r.Clock, mr.Status.Conditions, resourcesv1alpha1.ResourcesApplied)
for _, ref := range mr.Spec.SecretRefs {
secret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: ref.Name, Namespace: mr.Namespace}}
- if err := r.SourceClient.Get(reconcileCtx, client.ObjectKeyFromObject(secret), secret); err != nil {
+ if err := r.SourceClient.Get(ctx, client.ObjectKeyFromObject(secret), secret); err != nil {
conditionResourcesApplied = v1beta1helper.UpdatedConditionWithClock(r.Clock, conditionResourcesApplied, gardencorev1beta1.ConditionFalse, "CannotReadSecret", err.Error())
if err := updateConditions(ctx, r.SourceClient, mr, conditionResourcesApplied); err != nil {
return reconcile.Result{}, fmt.Errorf("could not update the ManagedResource status: %w", err)
@@ -311,7 +308,7 @@ func (r *Reconciler) reconcile(ctx context.Context, log logr.Logger, mr *resourc
}
}
- if deletionPending, err := r.cleanOldResources(reconcileCtx, log, mr, existingResourcesIndex); err != nil {
+ if deletionPending, err := r.cleanOldResources(ctx, log, mr, existingResourcesIndex); err != nil {
var (
reason string
status gardencorev1beta1.ConditionStatus
@@ -348,7 +345,7 @@ func (r *Reconciler) reconcile(ctx context.Context, log logr.Logger, mr *resourc
}
injectLabels := mergeMaps(mr.Spec.InjectLabels, map[string]string{resourcesv1alpha1.ManagedBy: *r.Config.ManagedByLabelValue})
- if err := r.applyNewResources(reconcileCtx, log, origin, newResourcesObjects, injectLabels, equivalences); err != nil {
+ if err := r.applyNewResources(ctx, log, origin, newResourcesObjects, injectLabels, equivalences); err != nil {
conditionResourcesApplied = v1beta1helper.UpdatedConditionWithClock(r.Clock, conditionResourcesApplied, gardencorev1beta1.ConditionFalse, resourcesv1alpha1.ConditionApplyFailed, err.Error())
if err := updateConditions(ctx, r.SourceClient, mr, conditionResourcesApplied); err != nil {
return reconcile.Result{}, fmt.Errorf("could not update the ManagedResource status: %w", err)
@@ -374,9 +371,6 @@ func (r *Reconciler) reconcile(ctx context.Context, log logr.Logger, mr *resourc
func (r *Reconciler) delete(ctx context.Context, log logr.Logger, mr *resourcesv1alpha1.ManagedResource) (reconcile.Result, error) {
log.Info("Started deleting resources created by ManagedResource")
- deleteCtx, cancel := controllerutils.GetMainReconciliationContext(ctx, r.Config.SyncPeriod.Duration)
- defer cancel()
-
if err := r.updateConditionsForDeletion(ctx, mr); err != nil {
return reconcile.Result{}, fmt.Errorf("could not update the ManagedResource status: %w", err)
}
@@ -397,7 +391,7 @@ func (r *Reconciler) delete(ctx context.Context, log logr.Logger, mr *resourcesv
return reconcile.Result{}, fmt.Errorf("could not update the ManagedResource status: %w", err)
}
- if deletionPending, err := r.cleanOldResources(deleteCtx, log, mr, existingResourcesIndex); err != nil {
+ if deletionPending, err := r.cleanOldResources(ctx, log, mr, existingResourcesIndex); err != nil {
var (
reason string
status gardencorev1beta1.ConditionStatus
diff --git a/pkg/resourcemanager/controller/networkpolicy/add.go b/pkg/resourcemanager/controller/networkpolicy/add.go
index 4fd1345383a..e7fecafa665 100644
--- a/pkg/resourcemanager/controller/networkpolicy/add.go
+++ b/pkg/resourcemanager/controller/networkpolicy/add.go
@@ -32,6 +32,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
+ "github.com/gardener/gardener/pkg/controllerutils"
)
// ControllerName is the name of the controller.
@@ -75,6 +76,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, targetCluster cluster.Clu
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(source.Kind[client.Object](
targetCluster.GetCache(),
diff --git a/pkg/resourcemanager/controller/networkpolicy/reconciler.go b/pkg/resourcemanager/controller/networkpolicy/reconciler.go
index 934d16755cf..9f4fca02fc7 100644
--- a/pkg/resourcemanager/controller/networkpolicy/reconciler.go
+++ b/pkg/resourcemanager/controller/networkpolicy/reconciler.go
@@ -47,9 +47,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
networkPolicyList := &metav1.PartialObjectMetadataList{}
networkPolicyList.SetGroupVersionKind(networkingv1.SchemeGroupVersion.WithKind("NetworkPolicyList"))
if err := r.TargetClient.List(ctx, networkPolicyList, client.MatchingLabels{
diff --git a/pkg/resourcemanager/controller/node/agentreconciliationdelay/add.go b/pkg/resourcemanager/controller/node/agentreconciliationdelay/add.go
index fd7d869d083..cc52d0a1ee6 100644
--- a/pkg/resourcemanager/controller/node/agentreconciliationdelay/add.go
+++ b/pkg/resourcemanager/controller/node/agentreconciliationdelay/add.go
@@ -29,7 +29,10 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, targetCluster cluster.Clu
return builder.
ControllerManagedBy(mgr).
Named(ControllerName).
- WithOptions(controller.Options{MaxConcurrentReconciles: 1}).
+ WithOptions(controller.Options{
+ MaxConcurrentReconciles: 1,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
+ }).
WatchesRawSource(
source.Kind[client.Object](targetCluster.GetCache(),
&corev1.Node{},
diff --git a/pkg/resourcemanager/controller/node/agentreconciliationdelay/reconciler.go b/pkg/resourcemanager/controller/node/agentreconciliationdelay/reconciler.go
index bd5a00bc4bc..0c05342f9f3 100644
--- a/pkg/resourcemanager/controller/node/agentreconciliationdelay/reconciler.go
+++ b/pkg/resourcemanager/controller/node/agentreconciliationdelay/reconciler.go
@@ -17,7 +17,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
- "github.com/gardener/gardener/pkg/controllerutils"
resourcemanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/resourcemanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/utils/flow"
kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
@@ -34,11 +33,8 @@ type Reconciler struct {
// Reconcile computes a time.Duration that can be used to delay reconciliations by using a simple linear mapping
// approach based on the indices of the nodes in the list of all nodes in the cluster. This way, the delays of all
// instances of gardener-node-agent are distributed evenly.
-func (r *Reconciler) Reconcile(reconcileCtx context.Context, _ reconcile.Request) (reconcile.Result, error) {
- log := logf.FromContext(reconcileCtx)
-
- ctx, cancel := controllerutils.GetMainReconciliationContext(reconcileCtx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
+func (r *Reconciler) Reconcile(ctx context.Context, _ reconcile.Request) (reconcile.Result, error) {
+ log := logf.FromContext(ctx)
nodeList := &corev1.NodeList{}
if err := r.TargetClient.List(ctx, nodeList); err != nil {
diff --git a/pkg/resourcemanager/controller/node/criticalcomponents/add.go b/pkg/resourcemanager/controller/node/criticalcomponents/add.go
index e037be77bba..68aedcd3dd7 100644
--- a/pkg/resourcemanager/controller/node/criticalcomponents/add.go
+++ b/pkg/resourcemanager/controller/node/criticalcomponents/add.go
@@ -17,6 +17,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -37,6 +38,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager, targetCluster cluster.Clu
Named(ControllerName).
WithOptions(controller.Options{
MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
WatchesRawSource(
source.Kind[client.Object](targetCluster.GetCache(),
diff --git a/pkg/resourcemanager/controller/node/criticalcomponents/reconciler.go b/pkg/resourcemanager/controller/node/criticalcomponents/reconciler.go
index 873aa8d7f5a..428fe7bafca 100644
--- a/pkg/resourcemanager/controller/node/criticalcomponents/reconciler.go
+++ b/pkg/resourcemanager/controller/node/criticalcomponents/reconciler.go
@@ -25,7 +25,6 @@ import (
"github.com/gardener/gardener/pkg/api/indexer"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
- "github.com/gardener/gardener/pkg/controllerutils"
resourcemanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/resourcemanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/resourcemanager/controller/node/criticalcomponents/helper"
"github.com/gardener/gardener/pkg/utils/kubernetes/health"
@@ -40,11 +39,8 @@ type Reconciler struct {
}
// Reconcile checks if the critical components not ready taint can be removed from the Node object.
-func (r *Reconciler) Reconcile(reconcileCtx context.Context, req reconcile.Request) (reconcile.Result, error) {
- log := logf.FromContext(reconcileCtx)
-
- ctx, cancel := controllerutils.GetMainReconciliationContext(reconcileCtx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
+func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
+ log := logf.FromContext(ctx)
node := &corev1.Node{}
if err := r.TargetClient.Get(ctx, req.NamespacedName, node); err != nil {
diff --git a/pkg/resourcemanager/webhook/nodeagentauthorizer/authorizer_test.go b/pkg/resourcemanager/webhook/nodeagentauthorizer/authorizer_test.go
index c2fe1f2ec00..c43d5f686dd 100644
--- a/pkg/resourcemanager/webhook/nodeagentauthorizer/authorizer_test.go
+++ b/pkg/resourcemanager/webhook/nodeagentauthorizer/authorizer_test.go
@@ -19,6 +19,8 @@ import (
"k8s.io/apimachinery/pkg/selection"
"k8s.io/apiserver/pkg/authentication/user"
auth "k8s.io/apiserver/pkg/authorization/authorizer"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
logzap "sigs.k8s.io/controller-runtime/pkg/log/zap"
@@ -55,7 +57,10 @@ var _ = Describe("Authorizer", func() {
ctx = context.Background()
log = logger.MustNewZapLogger(logger.DebugLevel, logger.FormatJSON, logzap.WriteTo(GinkgoWriter))
- sourceClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
+ objectTracker := testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())
+ sourceClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithObjectTracker(objectTracker).Build()
targetClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.ShootScheme).Build()
machineNamespace = "shoot--foo"
authorizer = NewAuthorizer(log, sourceClient, targetClient, &machineNamespace, true)
diff --git a/pkg/scheduler/apis/config/v1alpha1/validation/validation_test.go b/pkg/scheduler/apis/config/v1alpha1/validation/validation_test.go
index b31c7af8960..1a9f3926eb2 100644
--- a/pkg/scheduler/apis/config/v1alpha1/validation/validation_test.go
+++ b/pkg/scheduler/apis/config/v1alpha1/validation/validation_test.go
@@ -98,7 +98,7 @@ var _ = Describe("#ValidateConfiguration", func() {
Expect(ValidateConfiguration(conf)).To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
+ "Type": Equal(field.ErrorTypeRequired),
"Field": Equal("leaderElection.resourceNamespace"),
})),
))
diff --git a/pkg/scheduler/controller/shoot/add.go b/pkg/scheduler/controller/shoot/add.go
index c81e32cd207..39e17b64d4c 100644
--- a/pkg/scheduler/controller/shoot/add.go
+++ b/pkg/scheduler/controller/shoot/add.go
@@ -17,6 +17,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
"github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
+ "github.com/gardener/gardener/pkg/controllerutils"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
)
@@ -46,6 +47,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
)).
WithOptions(controller.Options{
MaxConcurrentReconciles: r.Config.ConcurrentSyncs,
+ ReconciliationTimeout: controllerutils.DefaultReconciliationTimeout,
}).
Complete(r)
}
diff --git a/pkg/scheduler/controller/shoot/reconciler.go b/pkg/scheduler/controller/shoot/reconciler.go
index 7d4bac36ead..38470648b86 100644
--- a/pkg/scheduler/controller/shoot/reconciler.go
+++ b/pkg/scheduler/controller/shoot/reconciler.go
@@ -28,7 +28,6 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
- "github.com/gardener/gardener/pkg/controllerutils"
schedulerconfigv1alpha1 "github.com/gardener/gardener/pkg/scheduler/apis/config/v1alpha1"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
cidrvalidation "github.com/gardener/gardener/pkg/utils/validation/cidr"
@@ -46,9 +45,6 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- ctx, cancel := controllerutils.GetMainReconciliationContext(ctx, controllerutils.DefaultReconciliationTimeout)
- defer cancel()
-
shoot := &gardencorev1beta1.Shoot{}
if err := r.Client.Get(ctx, request.NamespacedName, shoot); err != nil {
if apierrors.IsNotFound(err) {
diff --git a/pkg/utils/gardener/machines_test.go b/pkg/utils/gardener/machines_test.go
index e30e9f37bfd..2be9fdc4adf 100644
--- a/pkg/utils/gardener/machines_test.go
+++ b/pkg/utils/gardener/machines_test.go
@@ -13,6 +13,8 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -153,7 +155,10 @@ var _ = Describe("Machines", func() {
BeforeEach(func() {
fakeOps = &retryfake.Ops{MaxAttempts: 1}
- fakeClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
+ objectTracker := testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())
+ fakeClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithObjectTracker(objectTracker).Build()
DeferCleanup(test.WithVars(
&retry.Until, fakeOps.Until,
diff --git a/pkg/utils/gardener/shootstate/shootstate_test.go b/pkg/utils/gardener/shootstate/shootstate_test.go
index d9266760295..a3afcf61b94 100644
--- a/pkg/utils/gardener/shootstate/shootstate_test.go
+++ b/pkg/utils/gardener/shootstate/shootstate_test.go
@@ -15,6 +15,8 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/testing"
"k8s.io/utils/clock"
testclock "k8s.io/utils/clock/testing"
"k8s.io/utils/ptr"
@@ -45,7 +47,10 @@ var _ = Describe("ShootState", func() {
BeforeEach(func() {
fakeGardenClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.GardenScheme).Build()
- fakeSeedClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
+ // Starting with controller-runtime v0.22.0, the default object tracker does not work with resources which include
+ // structs directly as pointer, e.g. *MachineConfiguration in Machine resource. Hence, use the old one instead.
+ objectTracker := testing.NewObjectTracker(kubernetes.SeedScheme, scheme.Codecs.UniversalDecoder())
+ fakeSeedClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithObjectTracker(objectTracker).Build()
fakeClock = testclock.NewFakeClock(time.Now())
shoot = &gardencorev1beta1.Shoot{
@@ -128,7 +133,7 @@ var _ = Describe("ShootState", func() {
{
Name: "machine-state",
Type: "machine-state",
- Data: runtime.RawExtension{Raw: []byte(`{"state":"H4sIAAAAAAAC/+yUvW7jMAzH34WzPNjJLV4vy003JDcdMrASgbjQFySmQBDo3QvJdpKiKJo6CRC08WKJpEj6R/m/B4Ny01lakNduZ8hyhHYPqmzrvAzkdScxQjsTY/SSctj/PRhiVMiYAy0agnY8WkXiGkSxRo8yu+LGOa4qs6t8cM8k+3WxggAZCLlzdtUZiozGQ2u3WgtAax0XV+ktulLnaIWUBERPMnuHDn9rjDk6CWAyXiNT8Z70+0G9k1zymMQ6RaupiVJ+BERG3pZP0Bj5r6fQtz8Y/nmFTDnJcD4l8Rnh5jqENT6Rju9LQPrJ9NeH+37OZW+qIfjeZnLC0Qf30ikKfxbQHjZVp+ByxF8HLEBuQyDLyzcHp/wG9ci+vjp7p3Ke/CplL4B/z4TXSQw8m+ma3+RRzB6afzvNL4TnN9WX5qH5Z2l+P4pRd37d2Uy+t+b3QjOynz80f6Lmp/QaAAD//31qkngADAAA"}`)},
+ Data: runtime.RawExtension{Raw: []byte(`{"state":"H4sIAAAAAAAC/+yUPWv7MBDGv8vN8mAn/8XrP0unDkmnkuEqHcRFb0iXQgj67kWynaS0kJcWUtJ4sXR6Tjz80D1bMChXnaUZee02hixHaLegyrbOy0BedxIjtBMxqueUZc9bMMSokDELLRqCdmytInENolSjR5mP4so5riqzqXxwryT7damCALTWMXLnbLEQXbluX4WUBERPMp8ORv5rjFmdBDAZr5GpnO5tHfTIvdg6RYtjDSl/AiIjr4sljZEfPYXezlB48gqZFl12a9da555jYJqzwGh8IR0/3wTplqAtd6/rlKfVVIP4SigPsPjg3jpF4WEG7W5TdQpOJ3Y+LwFyHQJZnn9ovOQx1iPK+lKUTmV5/pXbv8HyNwBbJjHgaS7PvyaTndzz72sw058Y2uaP5l9PcBzaf9dBeRv510/piHJ6z78+/1J6DwAA//+Ak3pfGAoAAA=="}`)},
},
},
Extensions: []gardencorev1beta1.ExtensionResourceState{
diff --git a/pkg/utils/managedresources/registry_test.go b/pkg/utils/managedresources/registry_test.go
index 5db71609962..d2308d0d7e9 100644
--- a/pkg/utils/managedresources/registry_test.go
+++ b/pkg/utils/managedresources/registry_test.go
@@ -62,7 +62,6 @@ metadata:
foo.bar/test-07679f5e: "5"
foo.bar/test-d2718f1d: "6"
foo.bar/test-ea8edc28: "7"
- creationTimestamp: null
labels:
foo.bar/test-9dca243c: "1"
foo.bar/test-47fc132b: "2"
@@ -84,7 +83,6 @@ metadata:
roleBindingSerialized = `apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
- creationTimestamp: null
name: ` + roleBinding.Name + `
namespace: ` + roleBinding.Namespace + `
roleRef:
diff --git a/pkg/utils/validation/componentbaseconfig_test.go b/pkg/utils/validation/componentbaseconfig_test.go
index 4b497844b0d..89356c433a6 100644
--- a/pkg/utils/validation/componentbaseconfig_test.go
+++ b/pkg/utils/validation/componentbaseconfig_test.go
@@ -92,7 +92,7 @@ var _ = Describe("componentbaseconfig validation helpers", func() {
Expect(ValidateLeaderElectionConfiguration(config, fldPath)).To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
+ "Type": Equal(field.ErrorTypeRequired),
"Field": Equal(fldPath.Child("resourceNamespace").String()),
})),
))
diff --git a/pkg/webhook/authorizer/handler_test.go b/pkg/webhook/authorizer/handler_test.go
index 600abf9aaae..24169438b1a 100644
--- a/pkg/webhook/authorizer/handler_test.go
+++ b/pkg/webhook/authorizer/handler_test.go
@@ -45,7 +45,7 @@ var _ = Describe("Handler", func() {
handler.ServeHTTP(respRecorder, req)
- Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{},"status":{"allowed":false,"evaluationError":"422 request body is empty"}}
+ Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{},"spec":{},"status":{"allowed":false,"evaluationError":"422 request body is empty"}}
`))
})
@@ -57,7 +57,7 @@ var _ = Describe("Handler", func() {
handler.ServeHTTP(respRecorder, req)
- Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{},"status":{"allowed":false,"evaluationError":"400 fake-err"}}
+ Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{},"spec":{},"status":{"allowed":false,"evaluationError":"400 fake-err"}}
`))
})
@@ -69,7 +69,7 @@ var _ = Describe("Handler", func() {
handler.ServeHTTP(respRecorder, req)
- Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{},"status":{"allowed":false,"evaluationError":"400 contentType=foo, expected application/json"}}
+ Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{},"spec":{},"status":{"allowed":false,"evaluationError":"400 contentType=foo, expected application/json"}}
`))
})
@@ -81,7 +81,7 @@ var _ = Describe("Handler", func() {
handler.ServeHTTP(respRecorder, req)
- Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{},"status":{"allowed":false,"evaluationError":"400 couldn't get version/kind; json parse error: unexpected end of JSON input"}}
+ Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{},"spec":{},"status":{"allowed":false,"evaluationError":"400 couldn't get version/kind; json parse error: unexpected end of JSON input"}}
`))
})
@@ -97,7 +97,7 @@ var _ = Describe("Handler", func() {
handler = &Handler{Logger: log, Authorizer: &fakeAuthorizer{fn: fn}}
handler.ServeHTTP(respRecorder, req)
- Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{},"status":{` + expectedStatus + `}}
+ Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{},"spec":{},"status":{` + expectedStatus + `}}
`))
},
@@ -117,7 +117,7 @@ var _ = Describe("Handler", func() {
handler.ServeHTTP(respRecorder, req)
- Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1beta1","metadata":{"creationTimestamp":null},"spec":{},"status":{"allowed":true}}
+ Expect(respRecorder.Body.String()).To(Equal(`{"kind":"SubjectAccessReview","apiVersion":"authorization.k8s.io/v1beta1","metadata":{},"spec":{},"status":{"allowed":true}}
`))
})
})
diff --git a/plugin/pkg/managedseed/validator/admission_test.go b/plugin/pkg/managedseed/validator/admission_test.go
index ed65c1fc8aa..80e29e6b536 100644
--- a/plugin/pkg/managedseed/validator/admission_test.go
+++ b/plugin/pkg/managedseed/validator/admission_test.go
@@ -692,7 +692,7 @@ var _ = Describe("ManagedSeed", func() {
PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.gardenlet.config.seedConfig.spec.provider.zones"),
- "Detail": ContainSubstring("[]string{\"foo\", \"bar\"}: cannot use zone in seed provider that is not available in referenced shoot"),
+ "Detail": ContainSubstring("[\"foo\",\"bar\"]: cannot use zone in seed provider that is not available in referenced shoot"),
})),
))
})
@@ -911,7 +911,7 @@ var _ = Describe("ManagedSeed", func() {
PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.gardenlet.config.seedConfig.spec.provider.zones"),
- "Detail": ContainSubstring("[]string{\"zone-foobar\"}: added zones must match zone names configured for workers in the referenced shoot cluster"),
+ "Detail": ContainSubstring("[\"zone-foobar\"]: added zones must match zone names configured for workers in the referenced shoot cluster"),
})),
))
})
diff --git a/test/integration/nodeagent/operatingsystemconfig/operatingsystemconfig_test.go b/test/integration/nodeagent/operatingsystemconfig/operatingsystemconfig_test.go
index b2d3e8faa66..01e9ec7c686 100644
--- a/test/integration/nodeagent/operatingsystemconfig/operatingsystemconfig_test.go
+++ b/test/integration/nodeagent/operatingsystemconfig/operatingsystemconfig_test.go
@@ -500,7 +500,7 @@ inPlaceUpdates:
operatingSystem: false
serviceAccountKeyRotation: false
mustRestartNodeAgent: false
-operatingSystemConfigChecksum: 9f99a06a84314322dfbe80920a71938f4ac301874fc0e21c8fa5ad0d09baa98c
+operatingSystemConfigChecksum: ddafef1ed407f75f5fc6a8a075ff430fb03b348a4c00474978e2650a22edd9ff
units: {}
`, 0600)
@@ -1238,7 +1238,6 @@ contexts:
name: test-context
current-context: test-context
kind: Config
-preferences: {}
users:
- name: default-auth
user:
diff --git a/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_certificaterevocations.yaml b/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_certificaterevocations.yaml
index 21e9267458b..2d859cef082 100644
--- a/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_certificaterevocations.yaml
+++ b/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_certificaterevocations.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: certificaterevocations.cert.gardener.cloud
spec:
group: cert.gardener.cloud
diff --git a/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_certificates.yaml b/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_certificates.yaml
index a8d2b94484f..838d9439e8d 100644
--- a/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_certificates.yaml
+++ b/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_certificates.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: certificates.cert.gardener.cloud
spec:
group: cert.gardener.cloud
diff --git a/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_issuers.yaml b/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_issuers.yaml
index 31cbd8a8845..d0fe1d61589 100644
--- a/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_issuers.yaml
+++ b/test/integration/resourcemanager/health/crds/10-crd-cert.gardener.cloud_issuers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.18.0
+ controller-gen.kubebuilder.io/version: v0.19.0
name: issuers.cert.gardener.cloud
spec:
group: cert.gardener.cloud
diff --git a/third_party/mock/client-go/kubernetes/mocks.go b/third_party/mock/client-go/kubernetes/mocks.go
index 8b375db1c96..8b515ee3a20 100644
--- a/third_party/mock/client-go/kubernetes/mocks.go
+++ b/third_party/mock/client-go/kubernetes/mocks.go
@@ -49,26 +49,26 @@ import (
v1beta20 "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta2"
v1beta3 "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta3"
v111 "k8s.io/client-go/kubernetes/typed/networking/v1"
- v1alpha13 "k8s.io/client-go/kubernetes/typed/networking/v1alpha1"
v1beta110 "k8s.io/client-go/kubernetes/typed/networking/v1beta1"
v112 "k8s.io/client-go/kubernetes/typed/node/v1"
- v1alpha14 "k8s.io/client-go/kubernetes/typed/node/v1alpha1"
+ v1alpha13 "k8s.io/client-go/kubernetes/typed/node/v1alpha1"
v1beta111 "k8s.io/client-go/kubernetes/typed/node/v1beta1"
v113 "k8s.io/client-go/kubernetes/typed/policy/v1"
v1beta112 "k8s.io/client-go/kubernetes/typed/policy/v1beta1"
v114 "k8s.io/client-go/kubernetes/typed/rbac/v1"
- v1alpha15 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1"
+ v1alpha14 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1"
v1beta113 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1"
+ v115 "k8s.io/client-go/kubernetes/typed/resource/v1"
v1alpha3 "k8s.io/client-go/kubernetes/typed/resource/v1alpha3"
v1beta114 "k8s.io/client-go/kubernetes/typed/resource/v1beta1"
v1beta21 "k8s.io/client-go/kubernetes/typed/resource/v1beta2"
- v115 "k8s.io/client-go/kubernetes/typed/scheduling/v1"
- v1alpha16 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1"
+ v116 "k8s.io/client-go/kubernetes/typed/scheduling/v1"
+ v1alpha15 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1"
v1beta115 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1"
- v116 "k8s.io/client-go/kubernetes/typed/storage/v1"
- v1alpha17 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1"
+ v117 "k8s.io/client-go/kubernetes/typed/storage/v1"
+ v1alpha16 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1"
v1beta116 "k8s.io/client-go/kubernetes/typed/storage/v1beta1"
- v1alpha18 "k8s.io/client-go/kubernetes/typed/storagemigration/v1alpha1"
+ v1alpha17 "k8s.io/client-go/kubernetes/typed/storagemigration/v1alpha1"
)
// MockInterface is a mock of Interface interface.
@@ -599,20 +599,6 @@ func (mr *MockInterfaceMockRecorder) NetworkingV1() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetworkingV1", reflect.TypeOf((*MockInterface)(nil).NetworkingV1))
}
-// NetworkingV1alpha1 mocks base method.
-func (m *MockInterface) NetworkingV1alpha1() v1alpha13.NetworkingV1alpha1Interface {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "NetworkingV1alpha1")
- ret0, _ := ret[0].(v1alpha13.NetworkingV1alpha1Interface)
- return ret0
-}
-
-// NetworkingV1alpha1 indicates an expected call of NetworkingV1alpha1.
-func (mr *MockInterfaceMockRecorder) NetworkingV1alpha1() *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetworkingV1alpha1", reflect.TypeOf((*MockInterface)(nil).NetworkingV1alpha1))
-}
-
// NetworkingV1beta1 mocks base method.
func (m *MockInterface) NetworkingV1beta1() v1beta110.NetworkingV1beta1Interface {
m.ctrl.T.Helper()
@@ -642,10 +628,10 @@ func (mr *MockInterfaceMockRecorder) NodeV1() *gomock.Call {
}
// NodeV1alpha1 mocks base method.
-func (m *MockInterface) NodeV1alpha1() v1alpha14.NodeV1alpha1Interface {
+func (m *MockInterface) NodeV1alpha1() v1alpha13.NodeV1alpha1Interface {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NodeV1alpha1")
- ret0, _ := ret[0].(v1alpha14.NodeV1alpha1Interface)
+ ret0, _ := ret[0].(v1alpha13.NodeV1alpha1Interface)
return ret0
}
@@ -712,10 +698,10 @@ func (mr *MockInterfaceMockRecorder) RbacV1() *gomock.Call {
}
// RbacV1alpha1 mocks base method.
-func (m *MockInterface) RbacV1alpha1() v1alpha15.RbacV1alpha1Interface {
+func (m *MockInterface) RbacV1alpha1() v1alpha14.RbacV1alpha1Interface {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RbacV1alpha1")
- ret0, _ := ret[0].(v1alpha15.RbacV1alpha1Interface)
+ ret0, _ := ret[0].(v1alpha14.RbacV1alpha1Interface)
return ret0
}
@@ -739,6 +725,20 @@ func (mr *MockInterfaceMockRecorder) RbacV1beta1() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RbacV1beta1", reflect.TypeOf((*MockInterface)(nil).RbacV1beta1))
}
+// ResourceV1 mocks base method.
+func (m *MockInterface) ResourceV1() v115.ResourceV1Interface {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "ResourceV1")
+ ret0, _ := ret[0].(v115.ResourceV1Interface)
+ return ret0
+}
+
+// ResourceV1 indicates an expected call of ResourceV1.
+func (mr *MockInterfaceMockRecorder) ResourceV1() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResourceV1", reflect.TypeOf((*MockInterface)(nil).ResourceV1))
+}
+
// ResourceV1alpha3 mocks base method.
func (m *MockInterface) ResourceV1alpha3() v1alpha3.ResourceV1alpha3Interface {
m.ctrl.T.Helper()
@@ -782,10 +782,10 @@ func (mr *MockInterfaceMockRecorder) ResourceV1beta2() *gomock.Call {
}
// SchedulingV1 mocks base method.
-func (m *MockInterface) SchedulingV1() v115.SchedulingV1Interface {
+func (m *MockInterface) SchedulingV1() v116.SchedulingV1Interface {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SchedulingV1")
- ret0, _ := ret[0].(v115.SchedulingV1Interface)
+ ret0, _ := ret[0].(v116.SchedulingV1Interface)
return ret0
}
@@ -796,10 +796,10 @@ func (mr *MockInterfaceMockRecorder) SchedulingV1() *gomock.Call {
}
// SchedulingV1alpha1 mocks base method.
-func (m *MockInterface) SchedulingV1alpha1() v1alpha16.SchedulingV1alpha1Interface {
+func (m *MockInterface) SchedulingV1alpha1() v1alpha15.SchedulingV1alpha1Interface {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SchedulingV1alpha1")
- ret0, _ := ret[0].(v1alpha16.SchedulingV1alpha1Interface)
+ ret0, _ := ret[0].(v1alpha15.SchedulingV1alpha1Interface)
return ret0
}
@@ -824,10 +824,10 @@ func (mr *MockInterfaceMockRecorder) SchedulingV1beta1() *gomock.Call {
}
// StorageV1 mocks base method.
-func (m *MockInterface) StorageV1() v116.StorageV1Interface {
+func (m *MockInterface) StorageV1() v117.StorageV1Interface {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StorageV1")
- ret0, _ := ret[0].(v116.StorageV1Interface)
+ ret0, _ := ret[0].(v117.StorageV1Interface)
return ret0
}
@@ -838,10 +838,10 @@ func (mr *MockInterfaceMockRecorder) StorageV1() *gomock.Call {
}
// StorageV1alpha1 mocks base method.
-func (m *MockInterface) StorageV1alpha1() v1alpha17.StorageV1alpha1Interface {
+func (m *MockInterface) StorageV1alpha1() v1alpha16.StorageV1alpha1Interface {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StorageV1alpha1")
- ret0, _ := ret[0].(v1alpha17.StorageV1alpha1Interface)
+ ret0, _ := ret[0].(v1alpha16.StorageV1alpha1Interface)
return ret0
}
@@ -866,10 +866,10 @@ func (mr *MockInterfaceMockRecorder) StorageV1beta1() *gomock.Call {
}
// StoragemigrationV1alpha1 mocks base method.
-func (m *MockInterface) StoragemigrationV1alpha1() v1alpha18.StoragemigrationV1alpha1Interface {
+func (m *MockInterface) StoragemigrationV1alpha1() v1alpha17.StoragemigrationV1alpha1Interface {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StoragemigrationV1alpha1")
- ret0, _ := ret[0].(v1alpha18.StoragemigrationV1alpha1Interface)
+ ret0, _ := ret[0].(v1alpha17.StoragemigrationV1alpha1Interface)
return ret0
}
diff --git a/third_party/mock/controller-runtime/client/mocks.go b/third_party/mock/controller-runtime/client/mocks.go
index 4af03026ea6..851ec41129e 100644
--- a/third_party/mock/controller-runtime/client/mocks.go
+++ b/third_party/mock/controller-runtime/client/mocks.go
@@ -44,6 +44,25 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder {
return m.recorder
}
+// Apply mocks base method.
+func (m *MockClient) Apply(ctx context.Context, obj runtime.ApplyConfiguration, opts ...client.ApplyOption) error {
+ m.ctrl.T.Helper()
+ varargs := []any{ctx, obj}
+ for _, a := range opts {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "Apply", varargs...)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Apply indicates an expected call of Apply.
+func (mr *MockClientMockRecorder) Apply(ctx, obj any, opts ...any) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]any{ctx, obj}, opts...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*MockClient)(nil).Apply), varargs...)
+}
+
// Create mocks base method.
func (m *MockClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {
m.ctrl.T.Helper()
@@ -430,6 +449,25 @@ func (m *MockWriter) EXPECT() *MockWriterMockRecorder {
return m.recorder
}
+// Apply mocks base method.
+func (m *MockWriter) Apply(ctx context.Context, obj runtime.ApplyConfiguration, opts ...client.ApplyOption) error {
+ m.ctrl.T.Helper()
+ varargs := []any{ctx, obj}
+ for _, a := range opts {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "Apply", varargs...)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Apply indicates an expected call of Apply.
+func (mr *MockWriterMockRecorder) Apply(ctx, obj any, opts ...any) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]any{ctx, obj}, opts...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*MockWriter)(nil).Apply), varargs...)
+}
+
// Create mocks base method.
func (m *MockWriter) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {
m.ctrl.T.Helper()
From 0bafbc744ba41ea3dd826df82874c61ae0e07357 Mon Sep 17 00:00:00 2001
From: Vladimir Nachev
Date: Fri, 31 Oct 2025 00:05:55 +0200
Subject: [PATCH 003/176] Ensure already migrated CRBs are not duplicated in
the gardeneraccess MR (#13307)
---
cmd/gardenlet/app/migration.go | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/cmd/gardenlet/app/migration.go b/cmd/gardenlet/app/migration.go
index 67ad5dc6ff5..e378181acd9 100644
--- a/cmd/gardenlet/app/migration.go
+++ b/cmd/gardenlet/app/migration.go
@@ -117,6 +117,10 @@ func migrateAdminViewerKubeconfigClusterRoleBindings(ctx context.Context, log lo
return fmt.Errorf("failed to get objects for ManagedResource %q: %w", gardenerAccessKey, err)
}
+ gardenerAccessObjects = slices.DeleteFunc(gardenerAccessObjects, func(obj client.Object) bool {
+ return slices.Contains(crbs, obj.GetName())
+ })
+
gardenerAccessObjects = append(gardenerAccessObjects, gardeneraccess.ShootAccessClusterRoleBindings()...)
gardenerAccessRegistry := managedresources.NewRegistry(kubernetes.ShootScheme, kubernetes.ShootCodec, kubernetes.ShootSerializer)
gardenerAccessResources, err := gardenerAccessRegistry.AddAllAndSerialize(gardenerAccessObjects...)
From eba00b168c5d81b98fd467361ce4a01a572f3bff Mon Sep 17 00:00:00 2001
From: Marco Voelz
Date: Fri, 31 Oct 2025 10:03:05 +0100
Subject: [PATCH 004/176] Increase client-side rate limits for KCM (#13251)
* Increase client-side rate limits for KCM
* Move qps and burst settings to first args block
---
pkg/component/kubernetes/controllermanager/controllermanager.go | 2 ++
.../kubernetes/controllermanager/controllermanager_test.go | 2 ++
2 files changed, 4 insertions(+)
diff --git a/pkg/component/kubernetes/controllermanager/controllermanager.go b/pkg/component/kubernetes/controllermanager/controllermanager.go
index 7370b480289..5f3db5c1047 100644
--- a/pkg/component/kubernetes/controllermanager/controllermanager.go
+++ b/pkg/component/kubernetes/controllermanager/controllermanager.go
@@ -653,6 +653,8 @@ func (k *kubeControllerManager) computeCommand(port int32) []string {
"--authentication-kubeconfig=" + gardenerutils.PathGenericKubeconfig,
"--authorization-kubeconfig=" + gardenerutils.PathGenericKubeconfig,
"--kubeconfig=" + gardenerutils.PathGenericKubeconfig,
+ "--kube-api-qps=100",
+ "--kube-api-burst=200",
}
controllersToEnable = sets.New("*", "bootstrapsigner", "tokencleaner")
diff --git a/pkg/component/kubernetes/controllermanager/controllermanager_test.go b/pkg/component/kubernetes/controllermanager/controllermanager_test.go
index 5dd09dbf0b6..a0fac419b58 100644
--- a/pkg/component/kubernetes/controllermanager/controllermanager_test.go
+++ b/pkg/component/kubernetes/controllermanager/controllermanager_test.go
@@ -1000,6 +1000,8 @@ func commandForKubernetesVersion(
"--authentication-kubeconfig=/var/run/secrets/gardener.cloud/shoot/generic-kubeconfig/kubeconfig",
"--authorization-kubeconfig=/var/run/secrets/gardener.cloud/shoot/generic-kubeconfig/kubeconfig",
"--kubeconfig=/var/run/secrets/gardener.cloud/shoot/generic-kubeconfig/kubeconfig",
+ "--kube-api-qps=100",
+ "--kube-api-burst=200",
)
if !isWorkerless {
From 0629b6cc9caa8e272b437e6bf9b604a203d68170 Mon Sep 17 00:00:00 2001
From: Tim Ebert
Date: Fri, 31 Oct 2025 10:03:12 +0100
Subject: [PATCH 005/176] [GEP-28] Clean up some TODOs (#13290)
* Deploy machine CRDs in shoots with managed infrastructure
Previously, we only deployed the machine CRDs in `gardenadm bootstrap`.
With this, we also deploy it in `gardenadm init` for shoots with managed infrastructure.
* Disable high-availability-config webhook in bootstrap cluster
Disable the webhook in the kind cluster during `gardenadm bootstrap`, as it is not needed.
This also disables the webhook from the virtual garden, where it isn't needed either.
* Adapt CRDs unit test
---
.../gardener/resourcemanager/resource_manager.go | 7 +++++--
.../resourcemanager/resource_manager_test.go | 3 ++-
.../botanist/customresourcedefinitions.go | 5 +----
.../botanist/customresourcedefinitions_test.go | 14 ++++++++++----
pkg/gardenlet/controller/seed/seed/components.go | 1 +
.../operation/botanist/resource_manager.go | 3 ++-
.../controller/garden/garden/components.go | 1 +
7 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/pkg/component/gardener/resourcemanager/resource_manager.go b/pkg/component/gardener/resourcemanager/resource_manager.go
index bacadfa937d..42a585e4b20 100644
--- a/pkg/component/gardener/resourcemanager/resource_manager.go
+++ b/pkg/component/gardener/resourcemanager/resource_manager.go
@@ -249,6 +249,8 @@ type Values struct {
ClusterIdentity *string
// ConcurrentSyncs are the number of worker threads for concurrent reconciliation of resources
ConcurrentSyncs *int
+ // HighAvailabilityConfigWebhookEnabled controls whether the high availability config webhook is enabled.
+ HighAvailabilityConfigWebhookEnabled bool
// DefaultNotReadyTolerationSeconds indicates the tolerationSeconds of the toleration for notReady:NoExecute
DefaultNotReadyToleration *int64
// DefaultUnreachableTolerationSeconds indicates the tolerationSeconds of the toleration for unreachable:NoExecute
@@ -595,7 +597,7 @@ func (r *resourceManager) ensureConfigMap(ctx context.Context, configMap *corev1
Enabled: r.values.EndpointSliceHintsEnabled,
},
HighAvailabilityConfig: resourcemanagerconfigv1alpha1.HighAvailabilityConfigWebhookConfig{
- Enabled: !r.values.BootstrapControlPlaneNode,
+ Enabled: r.values.HighAvailabilityConfigWebhookEnabled,
DefaultNotReadyTolerationSeconds: r.values.DefaultNotReadyToleration,
DefaultUnreachableTolerationSeconds: r.values.DefaultUnreachableToleration,
},
@@ -1358,7 +1360,7 @@ func (r *resourceManager) newMutatingWebhookConfigurationWebhooks(
r.newProjectedTokenMountMutatingWebhook(namespaceSelector, secretServerCA, buildClientConfigFn),
}
- if !r.values.BootstrapControlPlaneNode {
+ if r.values.HighAvailabilityConfigWebhookEnabled {
webhooks = append(webhooks, NewHighAvailabilityConfigMutatingWebhook(namespaceSelector, objectSelector, secretServerCA, buildClientConfigFn))
}
@@ -2099,6 +2101,7 @@ func (r *resourceManager) GetValues() Values { return r.values }
// SetBootstrapControlPlaneNode sets the BootstrapControlPlaneNode field in the Values.
func (r *resourceManager) SetBootstrapControlPlaneNode(b bool) {
r.values.BootstrapControlPlaneNode = b
+ r.values.HighAvailabilityConfigWebhookEnabled = !b
}
func (r *resourceManager) skipStaticPods(webhooks []admissionregistrationv1.MutatingWebhook) {
diff --git a/pkg/component/gardener/resourcemanager/resource_manager_test.go b/pkg/component/gardener/resourcemanager/resource_manager_test.go
index 6449c427a86..c761b4ff1f1 100644
--- a/pkg/component/gardener/resourcemanager/resource_manager_test.go
+++ b/pkg/component/gardener/resourcemanager/resource_manager_test.go
@@ -304,6 +304,7 @@ var _ = Describe("ResourceManager", func() {
AlwaysUpdate: &alwaysUpdate,
ClusterIdentity: &clusterIdentity,
ConcurrentSyncs: &concurrentSyncs,
+ HighAvailabilityConfigWebhookEnabled: true,
DefaultNotReadyToleration: defaultNotReadyTolerationSeconds,
DefaultUnreachableToleration: defaultUnreachableTolerationSeconds,
NetworkPolicyAdditionalNamespaceSelectors: additionalNetworkPolicyNamespaceSelectors,
@@ -2679,9 +2680,9 @@ subjects:
}))
configMap = configMapFor(&watchedNamespace, ForSourceAndTarget, false, true)
- cfg.BootstrapControlPlaneNode = true
resourceManager = New(c, deployNamespace, sm, cfg)
resourceManager.SetSecrets(secrets)
+ resourceManager.SetBootstrapControlPlaneNode(true)
deployment = deploymentFor(configMap.Name, false, nil, true)
diff --git a/pkg/gardenadm/botanist/customresourcedefinitions.go b/pkg/gardenadm/botanist/customresourcedefinitions.go
index 31b2d2f737e..f350eb2d3bf 100644
--- a/pkg/gardenadm/botanist/customresourcedefinitions.go
+++ b/pkg/gardenadm/botanist/customresourcedefinitions.go
@@ -55,10 +55,7 @@ func (b *AutonomousBotanist) ReconcileCustomResourceDefinitions(ctx context.Cont
"ETCD": etcdCRDDeployer,
}
- // For now, we only deploy the machine CRDs in `gardenadm bootstrap`.
- // See https://github.com/gardener/gardener/pull/12152#discussion_r2101790385
- // TODO(timebertt): distinguish between scenarios in `gardenadm init`
- if !b.Shoot.RunsControlPlane() {
+ if b.Shoot.HasManagedInfrastructure() {
deployers["Machine"], err = machinecontrollermanager.NewCRD(b.SeedClientSet.Client())
if err != nil {
return fmt.Errorf("failed creating machine CRD deployer: %w", err)
diff --git a/pkg/gardenadm/botanist/customresourcedefinitions_test.go b/pkg/gardenadm/botanist/customresourcedefinitions_test.go
index b4141e1400e..f37373e8359 100644
--- a/pkg/gardenadm/botanist/customresourcedefinitions_test.go
+++ b/pkg/gardenadm/botanist/customresourcedefinitions_test.go
@@ -15,9 +15,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/rest"
+ "k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/client/kubernetes"
fakekubernetes "github.com/gardener/gardener/pkg/client/kubernetes/fake"
. "github.com/gardener/gardener/pkg/gardenadm/botanist"
@@ -60,9 +62,9 @@ var _ = Describe("CustomResourceDefinitions", func() {
})
Describe("#ReconcileCustomResourceDefinitions", func() {
- When("running the control plane", func() {
+ When("infrastructure is not managed by Gardener", func() {
BeforeEach(func() {
- b.Shoot.ControlPlaneNamespace = metav1.NamespaceSystem
+ b.Shoot.SetInfo(&gardencorev1beta1.Shoot{})
})
It("should reconcile all expected CRDs", func() {
@@ -114,9 +116,13 @@ var _ = Describe("CustomResourceDefinitions", func() {
})
})
- When("not running the control plane", func() {
+ When("infrastructure is managed by Gardener", func() {
BeforeEach(func() {
- b.Shoot.ControlPlaneNamespace = "shoot--foo--bar"
+ b.Shoot.SetInfo(&gardencorev1beta1.Shoot{
+ Spec: gardencorev1beta1.ShootSpec{
+ CredentialsBindingName: ptr.To("some-binding"),
+ },
+ })
})
It("should deploy the additional CRDs for the medium-touch scenario", func() {
diff --git a/pkg/gardenlet/controller/seed/seed/components.go b/pkg/gardenlet/controller/seed/seed/components.go
index 2a0d00c3f87..07c359d637c 100644
--- a/pkg/gardenlet/controller/seed/seed/components.go
+++ b/pkg/gardenlet/controller/seed/seed/components.go
@@ -294,6 +294,7 @@ func (r *Reconciler) newGardenerResourceManager(seed *gardencorev1beta1.Seed, se
return sharedcomponent.NewRuntimeGardenerResourceManager(r.SeedClientSet.Client(), r.GardenNamespace, secretsManager, resourcemanager.Values{
DefaultSeccompProfileEnabled: features.DefaultFeatureGate.Enabled(features.DefaultSeccompProfile),
+ HighAvailabilityConfigWebhookEnabled: true,
DefaultNotReadyToleration: defaultNotReadyTolerationSeconds,
DefaultUnreachableToleration: defaultUnreachableTolerationSeconds,
EndpointSliceHintsEnabled: endpointSliceHintsEnabled,
diff --git a/pkg/gardenlet/operation/botanist/resource_manager.go b/pkg/gardenlet/operation/botanist/resource_manager.go
index 609ec3a3f61..7521df47f16 100644
--- a/pkg/gardenlet/operation/botanist/resource_manager.go
+++ b/pkg/gardenlet/operation/botanist/resource_manager.go
@@ -35,6 +35,7 @@ func (b *Botanist) DefaultResourceManager() (resourcemanager.Interface, error) {
values = resourcemanager.Values{
ClusterIdentity: b.Seed.GetInfo().Status.ClusterIdentity,
+ HighAvailabilityConfigWebhookEnabled: true,
DefaultNotReadyToleration: defaultNotReadyTolerationSeconds,
DefaultUnreachableToleration: defaultUnreachableTolerationSeconds,
IsWorkerless: b.Shoot.IsWorkerless,
@@ -65,7 +66,7 @@ func (b *Botanist) DefaultResourceManager() (resourcemanager.Interface, error) {
values.TargetNamespaces = nil
} else {
newFunc = shared.NewRuntimeGardenerResourceManager
- // TODO(timebertt): consider disabling the highavailabilityconfig webhook
+ values.HighAvailabilityConfigWebhookEnabled = false
values.PriorityClassName = v1beta1constants.PriorityClassNameSeedSystemCritical
}
}
diff --git a/pkg/operator/controller/garden/garden/components.go b/pkg/operator/controller/garden/garden/components.go
index e3b5354be27..7aa5cee5806 100644
--- a/pkg/operator/controller/garden/garden/components.go
+++ b/pkg/operator/controller/garden/garden/components.go
@@ -396,6 +396,7 @@ func (r *Reconciler) newGardenerResourceManager(garden *operatorv1alpha1.Garden,
return sharedcomponent.NewRuntimeGardenerResourceManager(r.RuntimeClientSet.Client(), r.GardenNamespace, secretsManager, resourcemanager.Values{
DefaultSeccompProfileEnabled: features.DefaultFeatureGate.Enabled(features.DefaultSeccompProfile),
+ HighAvailabilityConfigWebhookEnabled: true,
DefaultNotReadyToleration: defaultNotReadyTolerationSeconds,
DefaultUnreachableToleration: defaultUnreachableTolerationSeconds,
EndpointSliceHintsEnabled: endpointSliceHintsEnabled,
From 234659f22dfa0c38d32b8b197fd4172afdc12541 Mon Sep 17 00:00:00 2001
From: Jonas Brand <101177682+8R0WNI3@users.noreply.github.com>
Date: Fri, 31 Oct 2025 12:05:05 +0100
Subject: [PATCH 006/176] Add default `.ocm/branch-info.yaml` file (#13281)
---
.ocm/branch-info.yaml | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .ocm/branch-info.yaml
diff --git a/.ocm/branch-info.yaml b/.ocm/branch-info.yaml
new file mode 100644
index 00000000000..94491fa6302
--- /dev/null
+++ b/.ocm/branch-info.yaml
@@ -0,0 +1,5 @@
+release-branch-template: release-v$major.$minor # e.g. release-v1.0
+branch-policy:
+ significant-part: minor # major, minor, patch
+ supported-versions-count: 3
+ release-cadence: 2w # d (days), w (weeks), y | yr (years)
From 87991d92e4ef759a0760b5463fc73b0a5874fa09 Mon Sep 17 00:00:00 2001
From: Plamen Kokanov <35485709+plkokanov@users.noreply.github.com>
Date: Fri, 31 Oct 2025 13:05:14 +0200
Subject: [PATCH 007/176] Fix flake in `NodeAgentAuthorizer` integration test
(#13287)
---
.../nodeagentauthorizer_suite_test.go | 137 ++++++++++++++++--
.../nodeagentauthorizer_test.go | 58 --------
2 files changed, 124 insertions(+), 71 deletions(-)
diff --git a/test/integration/resourcemanager/nodeagentauthorizer/nodeagentauthorizer_suite_test.go b/test/integration/resourcemanager/nodeagentauthorizer/nodeagentauthorizer_suite_test.go
index c7f789cc0dd..8823cb3f247 100644
--- a/test/integration/resourcemanager/nodeagentauthorizer/nodeagentauthorizer_suite_test.go
+++ b/test/integration/resourcemanager/nodeagentauthorizer/nodeagentauthorizer_suite_test.go
@@ -8,6 +8,7 @@ import (
"context"
"fmt"
"net"
+ "net/http"
"os"
"path/filepath"
"testing"
@@ -25,14 +26,20 @@ import (
clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest"
clientcmdv1 "k8s.io/client-go/tools/clientcmd/api/v1"
"k8s.io/utils/ptr"
+ "sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
+ controllerconfig "sigs.k8s.io/controller-runtime/pkg/config"
"sigs.k8s.io/controller-runtime/pkg/envtest"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+ metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
+ "sigs.k8s.io/controller-runtime/pkg/webhook"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
"github.com/gardener/gardener/pkg/component/kubernetes/apiserver"
"github.com/gardener/gardener/pkg/logger"
+ resourcemanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/resourcemanager/apis/config/v1alpha1"
resourcemanagerclient "github.com/gardener/gardener/pkg/resourcemanager/client"
"github.com/gardener/gardener/pkg/resourcemanager/webhook/nodeagentauthorizer"
"github.com/gardener/gardener/pkg/utils"
@@ -77,20 +84,30 @@ var _ = BeforeSuite(func() {
// determine a unique namespace name for test environment
testNamespaceName := testID + "-" + testRunID[:8]
- By("Create kubeconfig file for the authorization webhook")
+ By("Create kubeconfig files for the authorization webhooks")
webhookAddress, err := net.ResolveTCPAddr("tcp", net.JoinHostPort("localhost", "0"))
Expect(err).NotTo(HaveOccurred())
- webhookPort, _, err := netutils.SuggestPort("")
+ webhookPortNodeAgentMachine, _, err := netutils.SuggestPort("")
Expect(err).ToNot(HaveOccurred())
- kubeconfigFileName, err := createKubeconfigFileForAuthorizationWebhook(webhookAddress.IP.String(), webhookPort)
+ webhookPortNodeAgentNode, _, err := netutils.SuggestPort("")
+ Expect(err).ToNot(HaveOccurred())
+
+ kubeconfigFileNameMachine, err := createKubeconfigFileForAuthorizationWebhook(webhookAddress.IP.String(), webhookPortNodeAgentMachine)
+ Expect(err).ToNot(HaveOccurred())
+ DeferCleanup(func() {
+ By("Delete kubeconfig file for machine authorization webhook")
+ Expect(os.Remove(kubeconfigFileNameMachine)).To(Succeed())
+ })
+
+ kubeconfigFileNameNode, err := createKubeconfigFileForAuthorizationWebhook(webhookAddress.IP.String(), webhookPortNodeAgentNode)
Expect(err).ToNot(HaveOccurred())
DeferCleanup(func() {
- By("Delete kubeconfig file for authorization webhook")
- Expect(os.Remove(kubeconfigFileName)).To(Succeed())
+ By("Delete kubeconfig file for node authorization webhook")
+ Expect(os.Remove(kubeconfigFileNameNode)).To(Succeed())
})
By("Create authorization configuration file")
- authorizerConfigFileName, err := createAuthorizationConfigurationFile(kubeconfigFileName)
+ authorizerConfigFileName, err := createAuthorizationConfigurationFile(kubeconfigFileNameMachine, kubeconfigFileNameNode)
Expect(err).ToNot(HaveOccurred())
DeferCleanup(func() {
By("Delete authorization configuration file")
@@ -98,7 +115,8 @@ var _ = BeforeSuite(func() {
})
By("Start test environment")
- Expect(framework.FileExists(kubeconfigFileName)).To(BeTrue())
+ Expect(framework.FileExists(kubeconfigFileNameMachine)).To(BeTrue())
+ Expect(framework.FileExists(kubeconfigFileNameNode)).To(BeTrue())
testAPIServer := &envtest.APIServer{}
testAPIServer.Configure().
Set("authorization-config", authorizerConfigFileName).
@@ -118,7 +136,6 @@ var _ = BeforeSuite(func() {
ErrorIfCRDPathMissing: true,
WebhookInstallOptions: envtest.WebhookInstallOptions{
LocalServingHost: webhookAddress.IP.String(),
- LocalServingPort: webhookPort,
},
}
@@ -171,13 +188,86 @@ var _ = BeforeSuite(func() {
By("Delete test Namespace from test cluster")
Expect(testClient.Delete(ctx, testNamespace)).To(Or(Succeed(), BeNotFoundError()))
})
+
+ By("Setup managers")
+ mgrMachine, err := manager.New(testRestConfig, manager.Options{
+ WebhookServer: webhook.NewServer(webhook.Options{
+ Port: webhookPortNodeAgentMachine,
+ Host: testEnv.WebhookInstallOptions.LocalServingHost,
+ CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir,
+ }),
+ Metrics: metricsserver.Options{BindAddress: "0"},
+ Cache: cache.Options{
+ DefaultNamespaces: map[string]cache.Config{testNamespace.Name: {}},
+ },
+ Controller: controllerconfig.Controller{
+ SkipNameValidation: ptr.To(true),
+ },
+ })
+ Expect(err).NotTo(HaveOccurred())
+
+ mgrNode, err := manager.New(testRestConfig, manager.Options{
+ WebhookServer: webhook.NewServer(webhook.Options{
+ Port: webhookPortNodeAgentNode,
+ Host: testEnv.WebhookInstallOptions.LocalServingHost,
+ CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir,
+ }),
+ Metrics: metricsserver.Options{BindAddress: "0"},
+ Cache: cache.Options{
+ DefaultNamespaces: map[string]cache.Config{testNamespace.Name: {}},
+ },
+ Controller: controllerconfig.Controller{
+ SkipNameValidation: ptr.To(true),
+ },
+ })
+ Expect(err).NotTo(HaveOccurred())
+
+ By("Register webhooks")
+ nodeAgentMachineAuthorizer := &nodeagentauthorizer.Webhook{
+ Logger: log,
+ Config: resourcemanagerconfigv1alpha1.NodeAgentAuthorizerWebhookConfig{
+ Enabled: true,
+ MachineNamespace: &testNamespace.Name,
+ },
+ }
+ Expect(nodeAgentMachineAuthorizer.AddToManager(mgrMachine, testClient, testClient)).To(Succeed())
+
+ nodeAgentNodeAuthorizer := &nodeagentauthorizer.Webhook{
+ Logger: log,
+ Config: resourcemanagerconfigv1alpha1.NodeAgentAuthorizerWebhookConfig{
+ Enabled: true,
+ MachineNamespace: nil,
+ },
+ }
+ Expect(nodeAgentNodeAuthorizer.AddToManager(mgrNode, testClient, testClient)).To(Succeed())
+
+ By("Start managers")
+ for _, mgr := range []manager.Manager{mgrMachine, mgrNode} {
+ mgrContext, mgrCancel := context.WithCancel(ctx)
+
+ go func() {
+ defer GinkgoRecover()
+ Expect(mgr.Start(mgrContext)).To(Succeed())
+ }()
+
+ // Wait for the webhook server to start
+ Eventually(func() error {
+ checker := mgr.GetWebhookServer().StartedChecker()
+ return checker(&http.Request{})
+ }).Should(Succeed())
+
+ DeferCleanup(func() {
+ By("Stop manager")
+ mgrCancel()
+ })
+ }
})
func createKubeconfigFileForAuthorizationWebhook(address string, port int) (string, error) {
kubeconfig, err := runtime.Encode(clientcmdlatest.Codec, kubernetesutils.NewKubeconfig(
"authorization-webhook",
clientcmdv1.Cluster{
- Server: fmt.Sprintf("https://%s:%d%s", address, port, nodeagentauthorizer.WebhookPath),
+ Server: fmt.Sprintf("https://%s:%d%s", address, port, "/webhooks/auth/nodeagent"),
InsecureSkipTLSVerify: true,
},
clientcmdv1.AuthInfo{},
@@ -194,7 +284,7 @@ func createKubeconfigFileForAuthorizationWebhook(address string, port int) (stri
return kubeConfigFile.Name(), os.WriteFile(kubeConfigFile.Name(), kubeconfig, 0600)
}
-func createAuthorizationConfigurationFile(kubeconfigFileName string) (string, error) {
+func createAuthorizationConfigurationFile(kubeconfigFileNameMachine, kubeconfigFileNameNode string) (string, error) {
authorizationConfiguration := &apiserverv1beta1.AuthorizationConfiguration{
TypeMeta: metav1.TypeMeta{
APIVersion: apiserverv1beta1.ConfigSchemeGroupVersion.String(),
@@ -204,7 +294,28 @@ func createAuthorizationConfigurationFile(kubeconfigFileName string) (string, er
{Type: "RBAC", Name: "rbac"},
{
Type: "Webhook",
- Name: "node-agent-authorizer",
+ Name: "node-agent-authorizer-machine",
+ Webhook: &apiserverv1beta1.WebhookConfiguration{
+ // Set TTL to a very low value since it cannot be set to 0 because of defaulting.
+ // See https://github.com/kubernetes/apiserver/blob/3658357fea9fa8b36173d072f2d548f135049e05/pkg/apis/apiserver/v1/defaults.go#L52-L59
+ AuthorizedTTL: metav1.Duration{Duration: 1 * time.Nanosecond},
+ UnauthorizedTTL: metav1.Duration{Duration: 1 * time.Nanosecond},
+ Timeout: metav1.Duration{Duration: 1 * time.Second},
+ FailurePolicy: apiserverv1beta1.FailurePolicyDeny,
+ SubjectAccessReviewVersion: "v1",
+ MatchConditionSubjectAccessReviewVersion: "v1",
+ MatchConditions: []apiserverv1beta1.WebhookMatchCondition{{
+ Expression: fmt.Sprintf("'%s' in request.groups && request.user == 'gardener.cloud:node-agent:machine:%s'", v1beta1constants.NodeAgentsGroup, machineName),
+ }},
+ ConnectionInfo: apiserverv1beta1.WebhookConnectionInfo{
+ Type: apiserverv1beta1.AuthorizationWebhookConnectionInfoTypeKubeConfigFile,
+ KubeConfigFile: ptr.To(kubeconfigFileNameMachine),
+ },
+ },
+ },
+ {
+ Type: "Webhook",
+ Name: "node-agent-authorizer-node",
Webhook: &apiserverv1beta1.WebhookConfiguration{
// Set TTL to a very low value since it cannot be set to 0 because of defaulting.
// See https://github.com/kubernetes/apiserver/blob/3658357fea9fa8b36173d072f2d548f135049e05/pkg/apis/apiserver/v1/defaults.go#L52-L59
@@ -215,11 +326,11 @@ func createAuthorizationConfigurationFile(kubeconfigFileName string) (string, er
SubjectAccessReviewVersion: "v1",
MatchConditionSubjectAccessReviewVersion: "v1",
MatchConditions: []apiserverv1beta1.WebhookMatchCondition{{
- Expression: fmt.Sprintf("'%s' in request.groups", v1beta1constants.NodeAgentsGroup),
+ Expression: fmt.Sprintf("'%s' in request.groups && request.user == 'gardener.cloud:node-agent:machine:%s'", v1beta1constants.NodeAgentsGroup, nodeName),
}},
ConnectionInfo: apiserverv1beta1.WebhookConnectionInfo{
Type: apiserverv1beta1.AuthorizationWebhookConnectionInfoTypeKubeConfigFile,
- KubeConfigFile: ptr.To(kubeconfigFileName),
+ KubeConfigFile: ptr.To(kubeconfigFileNameNode),
},
},
},
diff --git a/test/integration/resourcemanager/nodeagentauthorizer/nodeagentauthorizer_test.go b/test/integration/resourcemanager/nodeagentauthorizer/nodeagentauthorizer_test.go
index 6955d78f3a5..a2a004b3456 100644
--- a/test/integration/resourcemanager/nodeagentauthorizer/nodeagentauthorizer_test.go
+++ b/test/integration/resourcemanager/nodeagentauthorizer/nodeagentauthorizer_test.go
@@ -5,11 +5,9 @@
package nodeagentauthorizer_test
import (
- "context"
"crypto/rand"
"crypto/x509/pkix"
"fmt"
- "net/http"
machinev1alpha1 "github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1"
. "github.com/onsi/ginkgo/v2"
@@ -23,17 +21,9 @@ import (
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/record"
certutil "k8s.io/client-go/util/cert"
- "k8s.io/utils/ptr"
- "sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
- controllerconfig "sigs.k8s.io/controller-runtime/pkg/config"
- "sigs.k8s.io/controller-runtime/pkg/manager"
- metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
- "sigs.k8s.io/controller-runtime/pkg/webhook"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
- resourcemanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/resourcemanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/resourcemanager/webhook/nodeagentauthorizer"
"github.com/gardener/gardener/pkg/utils"
secretsutils "github.com/gardener/gardener/pkg/utils/secrets"
. "github.com/gardener/gardener/pkg/utils/test/matchers"
@@ -58,54 +48,6 @@ var _ = Describe("NodeAgentAuthorizer tests", func() {
)
runTests := func() {
- BeforeEach(func() {
- By("Setup manager")
- mgr, err := manager.New(testRestConfig, manager.Options{
- WebhookServer: webhook.NewServer(webhook.Options{
- Port: testEnv.WebhookInstallOptions.LocalServingPort,
- Host: testEnv.WebhookInstallOptions.LocalServingHost,
- CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir,
- }),
- Metrics: metricsserver.Options{BindAddress: "0"},
- Cache: cache.Options{
- DefaultNamespaces: map[string]cache.Config{testNamespace.Name: {}},
- },
- Controller: controllerconfig.Controller{
- SkipNameValidation: ptr.To(true),
- },
- })
- Expect(err).NotTo(HaveOccurred())
-
- By("Register webhook")
- nodeAgentAuthorizer := &nodeagentauthorizer.Webhook{
- Logger: log,
- Config: resourcemanagerconfigv1alpha1.NodeAgentAuthorizerWebhookConfig{
- Enabled: true,
- MachineNamespace: machineNamespace,
- },
- }
- Expect(nodeAgentAuthorizer.AddToManager(mgr, testClient, testClient)).To(Succeed())
-
- By("Start manager")
- mgrContext, mgrCancel := context.WithCancel(ctx)
-
- go func() {
- defer GinkgoRecover()
- Expect(mgr.Start(mgrContext)).To(Succeed())
- }()
-
- // Wait for the webhook server to start
- Eventually(func() error {
- checker := mgr.GetWebhookServer().StartedChecker()
- return checker(&http.Request{})
- }).Should(Succeed())
-
- DeferCleanup(func() {
- By("Stop manager")
- mgrCancel()
- })
- })
-
Describe("#CertificateSigningRequests", func() {
var (
csr *certificatesv1.CertificateSigningRequest
From d1677e04ed93b4ac6a0768e4f425a91e1543e56e Mon Sep 17 00:00:00 2001
From: Sonu Kumar Singh
Date: Fri, 31 Oct 2025 16:35:21 +0530
Subject: [PATCH 008/176] Update log message for certificate reload (#13295)
---
extensions/pkg/webhook/certificates/reloader.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extensions/pkg/webhook/certificates/reloader.go b/extensions/pkg/webhook/certificates/reloader.go
index 5a683a8905e..ea6ce46b640 100644
--- a/extensions/pkg/webhook/certificates/reloader.go
+++ b/extensions/pkg/webhook/certificates/reloader.go
@@ -113,7 +113,7 @@ func (r *reloader) Reconcile(ctx context.Context, _ reconcile.Request) (reconcil
"certDir", r.certDir,
)
- log.V(1).Info("Reloading server certificate from secret")
+ log.V(1).Info("Checking for updated webhook server certificate in secret")
secretName, serverCert, serverKey, err := r.getServerCert(ctx, log, r.reader)
if err != nil {
From cd77ac132230ab5cb346d999478d088c08f2ce4a Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Fri, 31 Oct 2025 12:05:27 +0100
Subject: [PATCH 009/176] Update prometheus to v3.7.3 (#13296)
---
hack/tools.mk | 2 +-
imagevector/containers.yaml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hack/tools.mk b/hack/tools.mk
index cd51659bf59..69b5c6b0515 100644
--- a/hack/tools.mk
+++ b/hack/tools.mk
@@ -73,7 +73,7 @@ KUBECTL_VERSION ?= v1.34.1
# renovate: datasource=github-releases depName=kubernetes-sigs/kustomize
KUSTOMIZE_VERSION ?= v5.3.0
# renovate: datasource=github-releases depName=prometheus/prometheus
-PROMTOOL_VERSION ?= 3.7.2
+PROMTOOL_VERSION ?= 3.7.3
# renovate: datasource=github-releases depName=protocolbuffers/protobuf
PROTOC_VERSION ?= v33.0
# renovate: datasource=github-releases depName=GoogleContainerTools/skaffold
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index f83ce622b26..fdbaa6c03d3 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -229,7 +229,7 @@ images:
- name: prometheus
sourceRepository: github.com/prometheus/prometheus
repository: quay.io/prometheus/prometheus
- tag: v3.7.2
+ tag: v3.7.3
labels:
- name: gardener.cloud/cve-categorisation
value:
From 337792ff0c1f56e3190b1588b1ea353beb2d8dec Mon Sep 17 00:00:00 2001
From: Tobias Schlicht <155947440+tobschli@users.noreply.github.com>
Date: Fri, 31 Oct 2025 12:05:39 +0100
Subject: [PATCH 010/176] Do not wait for VPA CRDs when vpa is not enabled
(#13314)
There is a check already at the beginning of the reconciliation https://github.com/gardener/gardener/blob/b552e4362f99ab968cc259a245b5ebd48ed6ef8c/pkg/operator/controller/garden/garden/reconciler_reconcile.go\#L99-L105
---
pkg/operator/controller/garden/garden/reconciler_reconcile.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/pkg/operator/controller/garden/garden/reconciler_reconcile.go b/pkg/operator/controller/garden/garden/reconciler_reconcile.go
index 09eccf8c5f0..f907db9b1cf 100644
--- a/pkg/operator/controller/garden/garden/reconciler_reconcile.go
+++ b/pkg/operator/controller/garden/garden/reconciler_reconcile.go
@@ -709,6 +709,7 @@ func (r *Reconciler) runRuntimeSetupFlow(ctx context.Context, log logr.Logger, g
Name: "Waiting for custom resource definitions for VPA",
Fn: c.vpaCRD.Wait,
Dependencies: flow.NewTaskIDs(deployVPACRD),
+ SkipIf: !vpaEnabled(garden.Spec.RuntimeCluster.Settings),
})
waitForIstioCRD = g.Add(flow.Task{
From 103a6f6f8624eb8c0cfbf37420773014109d7419 Mon Sep 17 00:00:00 2001
From: Dominik Froehlich
Date: Fri, 31 Oct 2025 14:23:06 +0100
Subject: [PATCH 011/176] Fix typo in logging documentation (#13317)
---
docs/usage/observability/logging.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/usage/observability/logging.md b/docs/usage/observability/logging.md
index f6dd00e74ad..2118396b39e 100644
--- a/docs/usage/observability/logging.md
+++ b/docs/usage/observability/logging.md
@@ -66,7 +66,7 @@ If you are searching for logs for the past one hour, do not expect to see labels
By clicking on a value, Plutono automatically eliminates all other labels and/or values with which no valid log stream can be made.
After choosing the right labels and their values, click on the `Show logs` button.
This will build `Log query` and execute it.
-This approach is convenient when you don't know the labels names or they values.
+This approach is convenient when you don't know the label names or their values.

Once you feel comfortable, you can start to use the [LogQL](https://github.com/credativ/plutono) language to search for logs.
From 9267010aa24a0fef8fb15f8561aaaea643a897f8 Mon Sep 17 00:00:00 2001
From: Rafael Franzke
Date: Fri, 31 Oct 2025 17:37:04 +0100
Subject: [PATCH 012/176] Rename "Autonomous Shoot Clusters" to "Self-Hosted
Shoot Clusters" (#13273)
* Rename "Autonomous Shoot" to "Self-Hosted Shoot"
* Rename "medium touch" to "managed infrastructure" and "high touch" to "unmanaged infrastructure"
* [make generate]
* Address PR review feedback
---
Makefile | 8 +-
.../application/templates/rbac-user.yaml | 2 +-
charts/gardener/gardenlet/values.yaml | 4 +-
.../provider-local/templates/_helpers.tpl | 2 +-
.../provider-local/templates/deployment.yaml | 4 +-
charts/gardener/provider-local/values.yaml | 2 +-
cmd/gardenadm/app/app.go | 4 +-
.../app/app.go | 4 +-
cmd/gardenlet/app/app.go | 50 +++----
dev-setup/gardenadm.sh | 10 +-
dev-setup/gardenadm/machines/ippool.yaml | 2 +-
dev-setup/gardenadm/machines/machine.yaml | 6 +-
dev-setup/gardenadm/machines/namespace.yaml | 2 +-
.../{high-touch => managed-infra}/.gitkeep | 0
.../.gitkeep | 0
.../kustomization.yaml | 2 +-
.../patch-shoot-managed-infra.yaml} | 0
.../kustomization.yaml | 0
docs/README.md | 4 +-
docs/api-reference/core.md | 2 +-
docs/cli-reference/gardenadm/gardenadm.md | 4 +-
.../gardenadm/gardenadm_bootstrap.md | 6 +-
.../gardenadm/gardenadm_connect.md | 4 +-
.../gardenadm/gardenadm_discover.md | 2 +-
.../cli-reference/gardenadm/gardenadm_init.md | 2 +-
.../cli-reference/gardenadm/gardenadm_join.md | 4 +-
.../gardenadm/gardenadm_token.md | 2 +-
.../gardenadm/gardenadm_token_generate.md | 2 +-
.../gardenadm/gardenadm_version.md | 2 +-
docs/concepts/apiserver-admission-plugins.md | 2 +-
docs/concepts/controller-manager.md | 6 +-
docs/concepts/gardenadm.md | 28 ++--
.../getting_started_locally_with_gardenadm.md | 68 +++++-----
docs/extensions/provider-local.md | 2 +-
docs/extensions/registration.md | 2 +-
docs/extensions/shoot-webhooks.md | 6 +-
...rs.md => 28-self-hosted-shoot-clusters.md} | 128 +++++++++---------
example/90-shoot.yaml | 2 +-
extensions/pkg/controller/cmd/options.go | 18 +--
.../controlplane/genericactuator/actuator.go | 2 +-
.../pkg/controller/worker/controller.go | 10 +-
hack/ci-e2e-kind-gardenadm.sh | 20 +--
.../gardenletidentity/shoot/identity.go | 14 +-
.../gardenletidentity/shoot/identity_test.go | 18 +--
.../admission/shootrestriction/handler.go | 10 +-
.../webhook/auth/shoot/authorizer.go | 8 +-
.../webhook/auth/shoot/authorizer_test.go | 10 +-
.../webhook/auth/shoot/gardenadm.go | 2 +-
pkg/apis/core/helper/shoot.go | 6 +-
pkg/apis/core/helper/shoot_test.go | 10 +-
pkg/apis/core/types_shoot.go | 2 +-
.../core/v1beta1/constants/types_constants.go | 8 +-
pkg/apis/core/v1beta1/generated.proto | 2 +-
pkg/apis/core/v1beta1/helper/shoot.go | 15 +-
pkg/apis/core/v1beta1/helper/shoot_test.go | 16 +--
pkg/apis/core/v1beta1/types_shoot.go | 2 +-
pkg/apis/core/validation/shoot.go | 14 +-
pkg/apis/core/validation/shoot_test.go | 12 +-
pkg/apiserver/openapi/openapi_generated.go | 2 +-
.../operatingsystemconfig.go | 2 +-
.../garden/system/virtual/virtual.go | 2 +-
.../garden/system/virtual/virtual_test.go | 2 +-
.../resourcemanager/resource_manager.go | 2 +-
.../machine_controller_manager.go | 18 +--
.../machine_controller_manager_test.go | 8 +-
.../machinecontrollermanager/provider.go | 6 +-
.../machinecontrollermanager/provider_test.go | 4 +-
pkg/component/shared/resourcemanager.go | 2 +-
pkg/controller/gardenletdeployer/actuator.go | 6 +-
.../gardenletdeployer/actuator_test.go | 6 +-
.../certificatesigningrequest/reconciler.go | 2 +-
.../reconciler_test.go | 10 +-
pkg/gardenadm/botanist/bastion.go | 2 +-
pkg/gardenadm/botanist/botanist.go | 62 ++++-----
pkg/gardenadm/botanist/botanist_test.go | 42 +++---
pkg/gardenadm/botanist/controlplane.go | 32 ++---
pkg/gardenadm/botanist/controlplane_test.go | 4 +-
.../botanist/customresourcedefinitions.go | 4 +-
.../customresourcedefinitions_test.go | 6 +-
pkg/gardenadm/botanist/dnsrecord.go | 4 +-
pkg/gardenadm/botanist/etcd.go | 14 +-
pkg/gardenadm/botanist/extensions.go | 20 ++-
pkg/gardenadm/botanist/extensions_test.go | 8 +-
pkg/gardenadm/botanist/kubelet.go | 2 +-
pkg/gardenadm/botanist/kubelet_test.go | 4 +-
pkg/gardenadm/botanist/machines.go | 4 +-
pkg/gardenadm/botanist/network.go | 4 +-
pkg/gardenadm/botanist/network_test.go | 4 +-
pkg/gardenadm/botanist/nodeagent.go | 12 +-
pkg/gardenadm/botanist/nodeagent_test.go | 4 +-
.../botanist/operatingsystemconfig.go | 20 +--
.../botanist/operatingsystemconfig_test.go | 4 +-
pkg/gardenadm/botanist/secrets.go | 2 +-
pkg/gardenadm/botanist/secrets_test.go | 4 +-
pkg/gardenadm/botanist/ssh.go | 10 +-
pkg/gardenadm/botanist/system.go | 4 +-
pkg/gardenadm/cmd/bootstrap/bootstrap.go | 14 +-
pkg/gardenadm/cmd/connect/connect.go | 28 ++--
pkg/gardenadm/cmd/connect/options.go | 4 +-
pkg/gardenadm/cmd/init/init.go | 8 +-
pkg/gardenadm/cmd/join/join.go | 6 +-
pkg/gardenadm/cmd/token/create/options.go | 6 +-
.../cmd/token/create/options_test.go | 4 +-
pkg/gardenadm/cmd/token/generate/generate.go | 2 +-
pkg/gardenadm/cmd/token/utils/clientset.go | 4 +-
pkg/gardenlet/bootstrap/bootstrap.go | 12 +-
pkg/gardenlet/bootstrap/bootstrap_test.go | 16 +--
.../certificate/certificate_rotation.go | 12 +-
.../bootstrappers/garden_kubeconfig.go | 8 +-
pkg/gardenlet/controller/add.go | 6 +-
.../controllerinstallation/reconciler.go | 10 +-
pkg/gardenlet/controller/gardenlet/add.go | 2 +-
.../controller/gardenlet/reconciler.go | 2 +-
.../botanist/machinecontrollermanager.go | 2 +-
.../operation/botanist/resource_manager.go | 2 +-
pkg/gardenlet/operation/botanist/secrets.go | 8 +-
pkg/gardenlet/operation/botanist/worker.go | 4 +-
pkg/gardenlet/operation/shoot/shoot.go | 11 +-
pkg/gardenlet/operation/shoot/shoot_test.go | 10 +-
pkg/gardenlet/operation/shoot/types.go | 2 +-
.../controller/garden/garden/components.go | 2 +-
pkg/operator/controller/gardenlet/add.go | 2 +-
pkg/operator/controller/gardenlet/add_test.go | 4 +-
.../controller/dnsrecord/actuator.go | 10 +-
.../controller/dnsrecord/actuator_test.go | 4 +-
pkg/provider-local/controller/worker/add.go | 6 +-
pkg/provider-local/webhook/dnsconfig/add.go | 4 +-
pkg/scheduler/controller/shoot/add.go | 8 +-
pkg/scheduler/controller/shoot/add_test.go | 8 +-
pkg/utils/gardener/csr.go | 10 +-
pkg/utils/gardener/gardenlet/gardenlet.go | 14 +-
.../gardener/gardenlet/gardenlet_test.go | 22 +--
pkg/utils/gardener/shoot.go | 6 +-
pkg/utils/gardener/shoot_test.go | 4 +-
pkg/utils/graph/eventhandler_gardenlet.go | 10 +-
pkg/utils/graph/eventhandler_shoot.go | 2 +-
pkg/utils/graph/graph.go | 8 +-
pkg/utils/graph/graph_test.go | 2 +-
.../bootstraptoken/bootstraptoken.go | 6 +-
.../global/customverbauthorizer/admission.go | 8 +-
.../customverbauthorizer/admission_test.go | 14 +-
skaffold-gardenadm.yaml | 12 +-
test/e2e/gardenadm/e2e_suite_test.go | 4 +-
.../{mediumtouch => managedinfra}/exec.go | 2 +-
.../gardenadm.go | 10 +-
.../gardenadm.go | 8 +-
.../{hightouch => unmanagedinfra}/helper.go | 4 +-
.../certificatesigningrequest_test.go | 4 +-
.../controllerinstallation_test.go | 12 +-
149 files changed, 658 insertions(+), 662 deletions(-)
rename dev-setup/gardenadm/resources/generated/{high-touch => managed-infra}/.gitkeep (100%)
rename dev-setup/gardenadm/resources/generated/{medium-touch => unmanaged-infra}/.gitkeep (100%)
rename dev-setup/gardenadm/resources/overlays/{medium-touch => managed-infra}/kustomization.yaml (91%)
rename dev-setup/gardenadm/resources/overlays/{medium-touch/patch-shoot-medium-touch.yaml => managed-infra/patch-shoot-managed-infra.yaml} (100%)
rename dev-setup/gardenadm/resources/overlays/{high-touch => unmanaged-infra}/kustomization.yaml (100%)
rename docs/proposals/{28-autonomous-shoot-clusters.md => 28-self-hosted-shoot-clusters.md} (84%)
rename test/e2e/gardenadm/{mediumtouch => managedinfra}/exec.go (99%)
rename test/e2e/gardenadm/{mediumtouch => managedinfra}/gardenadm.go (97%)
rename test/e2e/gardenadm/{hightouch => unmanagedinfra}/gardenadm.go (97%)
rename test/e2e/gardenadm/{hightouch => unmanagedinfra}/helper.go (80%)
diff --git a/Makefile b/Makefile
index 3e3eb959264..3c5c917dd27 100644
--- a/Makefile
+++ b/Makefile
@@ -449,10 +449,10 @@ test-e2e-local-ha-multi-zone: $(GINKGO)
SHOOT_FAILURE_TOLERANCE_TYPE=zone USE_PROVIDER_LOCAL_COREDNS_SERVER=true ./hack/test-e2e-local.sh --procs=$(PARALLEL_E2E_TESTS) --label-filter "basic || (high-availability && update-to-zone)" ./test/e2e/gardener/...
test-e2e-local-operator: $(GINKGO)
./hack/test-e2e-local.sh operator --procs=1 --label-filter="default" ./test/e2e/operator/...
-test-e2e-local-gardenadm-medium-touch: $(GINKGO)
- ./hack/test-e2e-local.sh gardenadm --procs=1 --label-filter="medium-touch" ./test/e2e/gardenadm/...
-test-e2e-local-gardenadm-high-touch: $(GINKGO)
- ./hack/test-e2e-local.sh gardenadm --procs=1 --label-filter="high-touch" ./test/e2e/gardenadm/...
+test-e2e-local-gardenadm-managed-infra: $(GINKGO)
+ ./hack/test-e2e-local.sh gardenadm --procs=1 --label-filter="managed-infra" ./test/e2e/gardenadm/...
+test-e2e-local-gardenadm-unmanaged-infra: $(GINKGO)
+ ./hack/test-e2e-local.sh gardenadm --procs=1 --label-filter="unmanaged-infra" ./test/e2e/gardenadm/...
test-non-ha-pre-upgrade: $(GINKGO)
./hack/test-e2e-local.sh --procs=$(PARALLEL_E2E_TESTS) --label-filter="pre-upgrade && !high-availability" ./test/e2e/gardener/...
diff --git a/charts/gardener/controlplane/charts/application/templates/rbac-user.yaml b/charts/gardener/controlplane/charts/application/templates/rbac-user.yaml
index 9f3a8e91c7d..2480625ee7a 100644
--- a/charts/gardener/controlplane/charts/application/templates/rbac-user.yaml
+++ b/charts/gardener/controlplane/charts/application/templates/rbac-user.yaml
@@ -25,7 +25,7 @@ rules:
- modify-spec-kubernetes
- modify-spec-machineimages
- modify-spec-providerconfig
- - mark-autonomous
+ - mark-self-hosted
- apiGroups:
- seedmanagement.gardener.cloud
- dashboard.gardener.cloud
diff --git a/charts/gardener/gardenlet/values.yaml b/charts/gardener/gardenlet/values.yaml
index 7c8e839d227..34e95881590 100644
--- a/charts/gardener/gardenlet/values.yaml
+++ b/charts/gardener/gardenlet/values.yaml
@@ -221,5 +221,5 @@ nodeToleration:
# helm:
# ociRepository:
# ref:
-# name: name-of-autonomous-shoot
-# namespace: namespace-of-autonomous-shoot
+# name: name-of-self-hosted-shoot
+# namespace: namespace-of-self-hosted-shoot
diff --git a/charts/gardener/provider-local/templates/_helpers.tpl b/charts/gardener/provider-local/templates/_helpers.tpl
index 0526caf71e6..207e1857f98 100644
--- a/charts/gardener/provider-local/templates/_helpers.tpl
+++ b/charts/gardener/provider-local/templates/_helpers.tpl
@@ -23,7 +23,7 @@ policy/v1
{{- end -}}
{{- define "coredns.enabled" -}}
-{{- if or .Values.gardener.runtimeCluster.enabled .Values.gardener.autonomousShootCluster -}}
+{{- if or .Values.gardener.runtimeCluster.enabled .Values.gardener.selfHostedShootCluster -}}
false
{{- else -}}
{{ .Values.coredns.enabled }}
diff --git a/charts/gardener/provider-local/templates/deployment.yaml b/charts/gardener/provider-local/templates/deployment.yaml
index f6d065614ab..24ebabdc51e 100644
--- a/charts/gardener/provider-local/templates/deployment.yaml
+++ b/charts/gardener/provider-local/templates/deployment.yaml
@@ -95,8 +95,8 @@ spec:
{{- if .Values.gardener.version }}
- --gardener-version={{ .Values.gardener.version }}
{{- end }}
- {{- if .Values.gardener.autonomousShootCluster }}
- - --autonomous-shoot-cluster={{ .Values.gardener.autonomousShootCluster }}
+ {{- if .Values.gardener.selfHostedShootCluster }}
+ - --self-hosted-shoot-cluster={{ .Values.gardener.selfHostedShootCluster }}
{{- end }}
- --log-level={{ .Values.logLevel | default "info" }}
- --log-format={{ .Values.logFormat | default "json" }}
diff --git a/charts/gardener/provider-local/values.yaml b/charts/gardener/provider-local/values.yaml
index 03d98cf5b47..8eb662051ec 100644
--- a/charts/gardener/provider-local/values.yaml
+++ b/charts/gardener/provider-local/values.yaml
@@ -99,7 +99,7 @@ gardener:
provider: local
runtimeCluster:
enabled: false
- autonomousShootCluster: false
+ selfHostedShootCluster: false
usablePorts:
- 8080 # metrics
diff --git a/cmd/gardenadm/app/app.go b/cmd/gardenadm/app/app.go
index 7ecfc079331..f6a2d52a022 100644
--- a/cmd/gardenadm/app/app.go
+++ b/cmd/gardenadm/app/app.go
@@ -31,7 +31,7 @@ func NewCommand() *cobra.Command {
cmd := &cobra.Command{
Use: Name,
- Short: Name + " bootstraps and manages autonomous shoot clusters in the Gardener project.",
+ Short: Name + " bootstraps and manages self-hosted shoot clusters in the Gardener project.",
PersistentPreRunE: func(_ *cobra.Command, _ []string) error {
if err := opts.Validate(); err != nil {
return err
@@ -60,7 +60,7 @@ func NewCommand() *cobra.Command {
func prepareClusterBootstrapGroup(cmd *cobra.Command, opts *cmd.Options) {
group := &cobra.Group{
ID: "cluster-bootstrap",
- Title: "Autonomous Shoot Cluster Bootstrap Commands:",
+ Title: "Self-Hosted Shoot Cluster Bootstrap Commands:",
}
cmd.AddGroup(group)
diff --git a/cmd/gardener-extension-provider-local/app/app.go b/cmd/gardener-extension-provider-local/app/app.go
index 5e6a4617e3d..685e2dd1fd9 100644
--- a/cmd/gardener-extension-provider-local/app/app.go
+++ b/cmd/gardener-extension-provider-local/app/app.go
@@ -280,7 +280,7 @@ func NewControllerManagerCommand(ctx context.Context) *cobra.Command {
serviceCtrlOpts.Completed().Apply(&localservice.DefaultAddOptions)
workerCtrlOpts.Completed().Apply(&localworker.DefaultAddOptions.Controller)
localworker.DefaultAddOptions.GardenCluster = gardenCluster
- localworker.DefaultAddOptions.AutonomousShootCluster = generalOpts.Completed().AutonomousShootCluster
+ localworker.DefaultAddOptions.SelfHostedShootCluster = generalOpts.Completed().SelfHostedShootCluster
localBackupBucketOptions.Completed().Apply(&localbackupbucket.DefaultAddOptions)
localBackupBucketOptions.Completed().Apply(&localbackupentry.DefaultAddOptions)
heartbeatCtrlOptions.Completed().Apply(&heartbeat.DefaultAddOptions)
@@ -309,7 +309,7 @@ func NewControllerManagerCommand(ctx context.Context) *cobra.Command {
return fmt.Errorf("could not add readycheck of webhook to manager: %w", err)
}
- atomicShootWebhookConfig, err := webhookOptions.Completed().AddToManager(ctx, mgr, nil, generalOpts.Completed().AutonomousShootCluster)
+ atomicShootWebhookConfig, err := webhookOptions.Completed().AddToManager(ctx, mgr, nil, generalOpts.Completed().SelfHostedShootCluster)
if err != nil {
return fmt.Errorf("could not add webhooks to manager: %w", err)
}
diff --git a/cmd/gardenlet/app/app.go b/cmd/gardenlet/app/app.go
index d448f4747ec..a9cde085cc4 100644
--- a/cmd/gardenlet/app/app.go
+++ b/cmd/gardenlet/app/app.go
@@ -174,23 +174,23 @@ func run(ctx context.Context, cancel context.CancelFunc, log logr.Logger, cfg *g
return err
}
- if !gardenlet.IsResponsibleForAutonomousShoot() {
- // TODO(rfranzke): This healthz check is currently not enabled for autonomous shoots because it depends on the
+ if !gardenlet.IsResponsibleForSelfHostedShoot() {
+ // TODO(rfranzke): This healthz check is currently not enabled for self-hosted shoots because it depends on the
// seed-lease controller. This controller is currently not enabled, but it will be in the future. Once it is
- // enabled, we can also enable this healthz check for autonomous shoots.
+ // enabled, we can also enable this healthz check for self-hosted shoots.
if err := mgr.AddHealthzCheck("periodic-health", gardenerhealthz.CheckerFunc(healthManager)); err != nil {
return err
}
}
- var autonomousShootMeta *types.NamespacedName
- if gardenlet.IsResponsibleForAutonomousShoot() {
+ var selfHostedShootMeta *types.NamespacedName
+ if gardenlet.IsResponsibleForSelfHostedShoot() {
configMap := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: v1beta1constants.ConfigMapNameShootInfo, Namespace: metav1.NamespaceSystem}}
if err := mgr.GetAPIReader().Get(ctx, client.ObjectKeyFromObject(configMap), configMap); err != nil {
return fmt.Errorf("failed reading ConfigMap %s: %w", client.ObjectKeyFromObject(configMap), err)
}
- autonomousShootMeta = &types.NamespacedName{Namespace: configMap.Data["shootNamespace"], Name: configMap.Data["shootName"]}
- log.Info("Fetched information about autonomous shoot", "shootMeta", autonomousShootMeta)
+ selfHostedShootMeta = &types.NamespacedName{Namespace: configMap.Data["shootNamespace"], Name: configMap.Data["shootName"]}
+ log.Info("Fetched information about self-hosted shoot", "shootMeta", selfHostedShootMeta)
}
log.Info("Adding runnables to manager for bootstrapping")
@@ -203,7 +203,7 @@ func run(ctx context.Context, cancel context.CancelFunc, log logr.Logger, cfg *g
RuntimeClient: mgr.GetClient(),
Log: mgr.GetLogger().WithName("bootstrap"),
Config: cfg,
- AutonomousShootMeta: autonomousShootMeta,
+ SelfHostedShootMeta: selfHostedShootMeta,
Result: kubeconfigBootstrapResult,
},
},
@@ -212,7 +212,7 @@ func run(ctx context.Context, cancel context.CancelFunc, log logr.Logger, cfg *g
cancel: cancel,
mgr: mgr,
config: cfg,
- autonomousShootMeta: autonomousShootMeta,
+ selfHostedShootMeta: selfHostedShootMeta,
healthManager: healthManager,
kubeconfigBootstrapResult: kubeconfigBootstrapResult,
},
@@ -220,7 +220,7 @@ func run(ctx context.Context, cancel context.CancelFunc, log logr.Logger, cfg *g
}
)
- if !gardenlet.IsResponsibleForAutonomousShoot() {
+ if !gardenlet.IsResponsibleForSelfHostedShoot() {
runner.BootstrapRunnables = append([]manager.Runnable{
&bootstrappers.SeedConfigChecker{
SeedClient: mgr.GetClient(),
@@ -241,7 +241,7 @@ type garden struct {
cancel context.CancelFunc
mgr manager.Manager
config *gardenletconfigv1alpha1.GardenletConfiguration
- autonomousShootMeta *types.NamespacedName
+ selfHostedShootMeta *types.NamespacedName
healthManager gardenerhealthz.Manager
kubeconfigBootstrapResult *bootstrappers.KubeconfigBootstrapResult
}
@@ -271,7 +271,7 @@ func (g *garden) Start(ctx context.Context) error {
},
}
- if !gardenlet.IsResponsibleForAutonomousShoot() {
+ if !gardenlet.IsResponsibleForSelfHostedShoot() {
seedNamespace := gardenerutils.ComputeGardenNamespace(g.config.SeedConfig.Name)
opts.NewCache = func(config *rest.Config, opts cache.Options) (cache.Cache, error) {
@@ -361,12 +361,12 @@ func (g *garden) Start(ctx context.Context) error {
// gardenlet should watch only objects which are related to the shoot it is responsible for.
opts.ByObject = map[client.Object]cache.ByObject{
&gardencorev1beta1.Shoot{}: {
- Field: fields.SelectorFromSet(fields.Set{metav1.ObjectNameField: g.autonomousShootMeta.Name}),
- Namespaces: map[string]cache.Config{g.autonomousShootMeta.Namespace: {}},
+ Field: fields.SelectorFromSet(fields.Set{metav1.ObjectNameField: g.selfHostedShootMeta.Name}),
+ Namespaces: map[string]cache.Config{g.selfHostedShootMeta.Namespace: {}},
},
&seedmanagementv1alpha1.Gardenlet{}: {
- Field: fields.SelectorFromSet(fields.Set{metav1.ObjectNameField: gardenlet.ResourcePrefixAutonomousShoot + g.autonomousShootMeta.Name}),
- Namespaces: map[string]cache.Config{g.autonomousShootMeta.Namespace: {}},
+ Field: fields.SelectorFromSet(fields.Set{metav1.ObjectNameField: gardenlet.ResourcePrefixSelfHostedShoot + g.selfHostedShootMeta.Name}),
+ Namespaces: map[string]cache.Config{g.selfHostedShootMeta.Namespace: {}},
},
}
@@ -419,7 +419,7 @@ func (g *garden) Start(ctx context.Context) error {
return fmt.Errorf("failed waiting for cache to be synced")
}
- if !gardenlet.IsResponsibleForAutonomousShoot() {
+ if !gardenlet.IsResponsibleForSelfHostedShoot() {
log.Info("Registering Seed object in garden cluster")
if err := g.registerSeed(ctx, gardenCluster.GetClient()); err != nil {
return err
@@ -459,7 +459,7 @@ func (g *garden) Start(ctx context.Context) error {
}
if g.config.GardenClientConnection.KubeconfigSecret != nil {
- certificateManager, err := certificate.NewCertificateManager(log, gardenCluster, g.mgr.GetClient(), g.config, g.autonomousShootMeta)
+ certificateManager, err := certificate.NewCertificateManager(log, gardenCluster, g.mgr.GetClient(), g.config, g.selfHostedShootMeta)
if err != nil {
return fmt.Errorf("failed to create a new certificate manager: %w", err)
}
@@ -473,21 +473,21 @@ func (g *garden) Start(ctx context.Context) error {
return err
}
- if gardenlet.IsResponsibleForAutonomousShoot() {
+ if gardenlet.IsResponsibleForSelfHostedShoot() {
if err := retry.Until(ctx, 5*time.Second, func(ctx context.Context) (done bool, err error) {
- shoot := &gardencorev1beta1.Shoot{ObjectMeta: metav1.ObjectMeta{Name: g.autonomousShootMeta.Name, Namespace: g.autonomousShootMeta.Namespace}}
+ shoot := &gardencorev1beta1.Shoot{ObjectMeta: metav1.ObjectMeta{Name: g.selfHostedShootMeta.Name, Namespace: g.selfHostedShootMeta.Namespace}}
if err := gardenCluster.GetClient().Get(ctx, client.ObjectKeyFromObject(shoot), shoot); err != nil {
if !apierrors.IsNotFound(err) {
return retry.SevereError(err)
}
- log.Info("Shoot resource for autonomous shoot not found yet, waiting for it to be created in the Gardener API (usually, the 'gardenadm connect' command invocation creates it)", "shoot", g.autonomousShootMeta)
- return retry.MinorError(fmt.Errorf("the Shoot resource %s for autonomous shoot was not found yet", g.autonomousShootMeta))
+ log.Info("Shoot resource for self-hosted shoot not found yet, waiting for it to be created in the Gardener API (usually, the 'gardenadm connect' command invocation creates it)", "shoot", g.selfHostedShootMeta)
+ return retry.MinorError(fmt.Errorf("the Shoot resource %s for self-hosted shoot was not found yet", g.selfHostedShootMeta))
}
return retry.Ok()
}); err != nil {
- return fmt.Errorf("failed waiting for Shoot %s: %w", g.autonomousShootMeta, err)
+ return fmt.Errorf("failed waiting for Shoot %s: %w", g.selfHostedShootMeta, err)
}
- log.Info("Successfully fetched Shoot resource for autonomous shoot", "shoot", g.autonomousShootMeta)
+ log.Info("Successfully fetched Shoot resource for self-hosted shoot", "shoot", g.selfHostedShootMeta)
}
log.Info("Adding controllers to manager")
@@ -761,7 +761,7 @@ func (g *garden) overwriteGardenHostWhenDeployedInRuntimeCluster(ctx context.Con
func addAllFieldIndexes(ctx context.Context, i client.FieldIndexer) error {
// TODO(rfranzke): Revisit this once `gardenadm connect` progresses (currently, this causes informers to be started
// against the API server, but gardenlet does not have the needed permissions).
- if gardenlet.IsResponsibleForAutonomousShoot() {
+ if gardenlet.IsResponsibleForSelfHostedShoot() {
return nil
}
diff --git a/dev-setup/gardenadm.sh b/dev-setup/gardenadm.sh
index e960501ede1..4f85fa26ca4 100755
--- a/dev-setup/gardenadm.sh
+++ b/dev-setup/gardenadm.sh
@@ -9,8 +9,8 @@ set -o pipefail
COMMAND="${1:-up}"
VALID_COMMANDS=("up" "down")
-SCENARIO="${SCENARIO:-high-touch}"
-VALID_SCENARIOS=("high-touch" "medium-touch" "connect")
+SCENARIO="${SCENARIO:-unmanaged-infra}"
+VALID_SCENARIOS=("unmanaged-infra" "managed-infra" "connect")
valid_scenario=false
for scenario in "${VALID_SCENARIOS[@]}"; do
@@ -28,7 +28,7 @@ case "$COMMAND" in
up)
if [[ "$SCENARIO" != "connect" ]]; then
# Prepare resources and generate manifests.
- # The manifests are copied to the high-touch machine pods or can be passed to the `--config-dir` flag of `gardenadm bootstrap`.
+ # The manifests are copied to the unmanaged-infra machine pods or can be passed to the `--config-dir` flag of `gardenadm bootstrap`.
skaffold build \
-p "$SCENARIO" \
-m gardenadm,provider-local-node,provider-local \
@@ -42,9 +42,9 @@ case "$COMMAND" in
--build-artifacts \
-
- if [[ "$SCENARIO" == "high-touch" ]]; then
+ if [[ "$SCENARIO" == "unmanaged-infra" ]]; then
skaffold run \
- -n gardenadm-high-touch \
+ -n gardenadm-unmanaged-infra \
-m provider-local-node,machine
fi
diff --git a/dev-setup/gardenadm/machines/ippool.yaml b/dev-setup/gardenadm/machines/ippool.yaml
index dcbcfa668fa..6077a5d328f 100644
--- a/dev-setup/gardenadm/machines/ippool.yaml
+++ b/dev-setup/gardenadm/machines/ippool.yaml
@@ -1,7 +1,7 @@
apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
- name: gardenadm-high-touch
+ name: gardenadm-unmanaged-infra
spec:
cidr: 10.0.0.0/16
ipipMode: Always
diff --git a/dev-setup/gardenadm/machines/machine.yaml b/dev-setup/gardenadm/machines/machine.yaml
index fad0c98acb9..5c29819b444 100644
--- a/dev-setup/gardenadm/machines/machine.yaml
+++ b/dev-setup/gardenadm/machines/machine.yaml
@@ -15,7 +15,7 @@ spec:
labels:
app: machine
annotations:
- cni.projectcalico.org/ipv4pools: '["gardenadm-high-touch"]'
+ cni.projectcalico.org/ipv4pools: '["gardenadm-unmanaged-infra"]'
spec:
containers:
- name: node
@@ -42,7 +42,7 @@ spec:
- name: bashrc
mountPath: /root/.bashrc
subPath: bashrc
- # we don't want components of the autonomous shoot cluster to communicate with the kind API server
+ # we don't want components of the self-hosted shoot cluster to communicate with the kind API server
automountServiceAccountToken: false
hostAliases:
- hostnames:
@@ -77,7 +77,7 @@ kind: ConfigMap
metadata:
name: machine-bashrc
labels:
- app: high-touch-machine
+ app: unmanaged-infra-machine
data:
bashrc: |
export KUBECONFIG=/etc/kubernetes/admin.conf
diff --git a/dev-setup/gardenadm/machines/namespace.yaml b/dev-setup/gardenadm/machines/namespace.yaml
index 31ea660a287..bd8ce7b8363 100644
--- a/dev-setup/gardenadm/machines/namespace.yaml
+++ b/dev-setup/gardenadm/machines/namespace.yaml
@@ -1,7 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
- name: gardenadm-high-touch
+ name: gardenadm-unmanaged-infra
labels:
# Use label so that machine pods are considered in the export_artifacts() helper function during test runs in Prow.
# This makes sure that the usual systemd and pod logs get exported for each machine pod in this namespace.
diff --git a/dev-setup/gardenadm/resources/generated/high-touch/.gitkeep b/dev-setup/gardenadm/resources/generated/managed-infra/.gitkeep
similarity index 100%
rename from dev-setup/gardenadm/resources/generated/high-touch/.gitkeep
rename to dev-setup/gardenadm/resources/generated/managed-infra/.gitkeep
diff --git a/dev-setup/gardenadm/resources/generated/medium-touch/.gitkeep b/dev-setup/gardenadm/resources/generated/unmanaged-infra/.gitkeep
similarity index 100%
rename from dev-setup/gardenadm/resources/generated/medium-touch/.gitkeep
rename to dev-setup/gardenadm/resources/generated/unmanaged-infra/.gitkeep
diff --git a/dev-setup/gardenadm/resources/overlays/medium-touch/kustomization.yaml b/dev-setup/gardenadm/resources/overlays/managed-infra/kustomization.yaml
similarity index 91%
rename from dev-setup/gardenadm/resources/overlays/medium-touch/kustomization.yaml
rename to dev-setup/gardenadm/resources/overlays/managed-infra/kustomization.yaml
index f8d0cca8176..111f5bf56bc 100644
--- a/dev-setup/gardenadm/resources/overlays/medium-touch/kustomization.yaml
+++ b/dev-setup/gardenadm/resources/overlays/managed-infra/kustomization.yaml
@@ -11,7 +11,7 @@ components:
- ../../../../gardenconfig/components/credentials/secret-project-garden
patches:
-- path: patch-shoot-medium-touch.yaml
+- path: patch-shoot-managed-infra.yaml
- target:
kind: Shoot
patch: |
diff --git a/dev-setup/gardenadm/resources/overlays/medium-touch/patch-shoot-medium-touch.yaml b/dev-setup/gardenadm/resources/overlays/managed-infra/patch-shoot-managed-infra.yaml
similarity index 100%
rename from dev-setup/gardenadm/resources/overlays/medium-touch/patch-shoot-medium-touch.yaml
rename to dev-setup/gardenadm/resources/overlays/managed-infra/patch-shoot-managed-infra.yaml
diff --git a/dev-setup/gardenadm/resources/overlays/high-touch/kustomization.yaml b/dev-setup/gardenadm/resources/overlays/unmanaged-infra/kustomization.yaml
similarity index 100%
rename from dev-setup/gardenadm/resources/overlays/high-touch/kustomization.yaml
rename to dev-setup/gardenadm/resources/overlays/unmanaged-infra/kustomization.yaml
diff --git a/docs/README.md b/docs/README.md
index 8c763807b25..f1e13e09bc3 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -154,7 +154,7 @@
* [GEP-25: Namespaced Cloud Profiles](proposals/25-namespaced-cloud-profiles.md)
* [GEP-26: Workload Identity - Trust Based Authentication](proposals/26-workload-identity.md)
* [GEP-27: Add Optional Bastion Section To CloudProfile](proposals/27-cloudprofile-bastion-section.md)
-* [GEP-28: Autonomous Shoot Clusters](proposals/28-autonomous-shoot-clusters.md)
+* [GEP-28: Self-Hosted Shoot Clusters](proposals/28-self-hosted-shoot-clusters.md)
* [GEP-30: Rework API Server Proxy to Drop Proxy Protocol](proposals/30-apiserver-proxy.md)
* [GEP-31: In-Place Node Updates of Shoot Clusters](proposals/31-inplace-node-update.md)
* [GEP-32: Cloud Profile Version Classification Lifecycles](proposals/32-version-classification-lifecycles.md)
@@ -235,7 +235,7 @@
* [Getting started locally](deployment/getting_started_locally.md)
* [Getting started locally with extensions](deployment/getting_started_locally_with_extensions.md)
-* [Getting started locally with Autonomous Shoot Clusters](deployment/getting_started_locally_with_gardenadm.md)
+* [Getting started locally with Self-Hosted Shoot Clusters](deployment/getting_started_locally_with_gardenadm.md)
* [Setup Gardener on a Kubernetes cluster](deployment/setup_gardener.md)
* [Version Skew Policy](deployment/version_skew_policy.md)
* [Deploying Gardenlets](deployment/deploy_gardenlet.md)
diff --git a/docs/api-reference/core.md b/docs/api-reference/core.md
index 17c30ec8cfb..370dddc5ad2 100644
--- a/docs/api-reference/core.md
+++ b/docs/api-reference/core.md
@@ -15038,7 +15038,7 @@ WorkerControlPlane
(Optional)
ControlPlane specifies that the shoot cluster control plane components should be running in this worker pool.
-This is only relevant for autonomous shoot clusters.
+This is only relevant for self-hosted shoot clusters.
diff --git a/docs/cli-reference/gardenadm/gardenadm.md b/docs/cli-reference/gardenadm/gardenadm.md
index 19a1a97065d..793db701a9e 100644
--- a/docs/cli-reference/gardenadm/gardenadm.md
+++ b/docs/cli-reference/gardenadm/gardenadm.md
@@ -1,6 +1,6 @@
## gardenadm
-gardenadm bootstraps and manages autonomous shoot clusters in the Gardener project.
+gardenadm bootstraps and manages self-hosted shoot clusters in the Gardener project.
### Options
@@ -12,7 +12,7 @@ gardenadm bootstraps and manages autonomous shoot clusters in the Gardener proje
### SEE ALSO
-* [gardenadm bootstrap](gardenadm_bootstrap.md) - Bootstrap the infrastructure for an Autonomous Shoot Cluster
+* [gardenadm bootstrap](gardenadm_bootstrap.md) - Bootstrap the infrastructure for a Self-Hosted Shoot Cluster
* [gardenadm connect](gardenadm_connect.md) - Deploy a gardenlet for further cluster management
* [gardenadm discover](gardenadm_discover.md) - Conveniently download Gardener configuration resources from an existing garden cluster
* [gardenadm init](gardenadm_init.md) - Bootstrap the first control plane node
diff --git a/docs/cli-reference/gardenadm/gardenadm_bootstrap.md b/docs/cli-reference/gardenadm/gardenadm_bootstrap.md
index 02a3e69dd63..a4358e05bae 100644
--- a/docs/cli-reference/gardenadm/gardenadm_bootstrap.md
+++ b/docs/cli-reference/gardenadm/gardenadm_bootstrap.md
@@ -1,10 +1,10 @@
## gardenadm bootstrap
-Bootstrap the infrastructure for an Autonomous Shoot Cluster
+Bootstrap the infrastructure for a Self-Hosted Shoot Cluster
### Synopsis
-Bootstrap the infrastructure for an Autonomous Shoot Cluster (networks, machines, etc.)
+Bootstrap the infrastructure for a Self-Hosted Shoot Cluster (networks, machines, etc.)
```
gardenadm bootstrap [flags]
@@ -36,5 +36,5 @@ gardenadm bootstrap --config-dir /path/to/manifests
### SEE ALSO
-* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages autonomous shoot clusters in the Gardener project.
+* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages self-hosted shoot clusters in the Gardener project.
diff --git a/docs/cli-reference/gardenadm/gardenadm_connect.md b/docs/cli-reference/gardenadm/gardenadm_connect.md
index 978fe8d8fc0..d1d780dda69 100644
--- a/docs/cli-reference/gardenadm/gardenadm_connect.md
+++ b/docs/cli-reference/gardenadm/gardenadm_connect.md
@@ -20,7 +20,7 @@ gardenadm connect
### Options
```
- --bootstrap-token string Bootstrap token for connecting the autonomous shoot cluster to a garden cluster (create it with 'gardenadm token' in the garden cluster)
+ --bootstrap-token string Bootstrap token for connecting the self-hosted shoot cluster to a garden cluster (create it with 'gardenadm token' in the garden cluster)
--ca-certificate bytesBase64 Base64-encoded certificate authority bundle of the Gardener control plane
-d, --config-dir string Path to a directory containing the Gardener configuration files for the init command, i.e., files containing resources like CloudProfile, Shoot, etc. The files must be in YAML/JSON and have .{yaml,yml,json} file extensions to be considered.
--force Forces the deployment of gardenlet, even if it already exists
@@ -36,5 +36,5 @@ gardenadm connect
### SEE ALSO
-* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages autonomous shoot clusters in the Gardener project.
+* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages self-hosted shoot clusters in the Gardener project.
diff --git a/docs/cli-reference/gardenadm/gardenadm_discover.md b/docs/cli-reference/gardenadm/gardenadm_discover.md
index 43ab2746ee3..add28f7c927 100644
--- a/docs/cli-reference/gardenadm/gardenadm_discover.md
+++ b/docs/cli-reference/gardenadm/gardenadm_discover.md
@@ -35,5 +35,5 @@ gardenadm discover
### SEE ALSO
-* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages autonomous shoot clusters in the Gardener project.
+* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages self-hosted shoot clusters in the Gardener project.
diff --git a/docs/cli-reference/gardenadm/gardenadm_init.md b/docs/cli-reference/gardenadm/gardenadm_init.md
index 403a330d8df..c0079025a87 100644
--- a/docs/cli-reference/gardenadm/gardenadm_init.md
+++ b/docs/cli-reference/gardenadm/gardenadm_init.md
@@ -33,5 +33,5 @@ gardenadm init --config-dir /path/to/manifests
### SEE ALSO
-* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages autonomous shoot clusters in the Gardener project.
+* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages self-hosted shoot clusters in the Gardener project.
diff --git a/docs/cli-reference/gardenadm/gardenadm_join.md b/docs/cli-reference/gardenadm/gardenadm_join.md
index f0b789b874f..760bb6fb6a3 100644
--- a/docs/cli-reference/gardenadm/gardenadm_join.md
+++ b/docs/cli-reference/gardenadm/gardenadm_join.md
@@ -6,7 +6,7 @@ Bootstrap worker nodes and join them to the cluster
Bootstrap worker nodes and join them to the cluster.
-This command helps to initialize and configure a node to join an existing autonomous shoot cluster.
+This command helps to initialize and configure a node to join an existing self-hosted shoot cluster.
It ensures that the necessary configurations are applied and the node is properly registered as a worker or control plane node.
Note that further control plane nodes cannot be joined currently.
@@ -40,5 +40,5 @@ gardenadm join --bootstrap-token --ca-certificate --gardener-n
### SEE ALSO
-* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages autonomous shoot clusters in the Gardener project.
+* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages self-hosted shoot clusters in the Gardener project.
diff --git a/docs/cli-reference/gardenadm/gardenadm_token.md b/docs/cli-reference/gardenadm/gardenadm_token.md
index 66098e6cfed..004db09a173 100644
--- a/docs/cli-reference/gardenadm/gardenadm_token.md
+++ b/docs/cli-reference/gardenadm/gardenadm_token.md
@@ -21,7 +21,7 @@ Manage bootstrap and discovery tokens for gardenadm join
### SEE ALSO
-* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages autonomous shoot clusters in the Gardener project.
+* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages self-hosted shoot clusters in the Gardener project.
* [gardenadm token create](gardenadm_token_create.md) - Create a bootstrap token on the cluster for joining a node or connecting a Shoot to Gardener
* [gardenadm token delete](gardenadm_token_delete.md) - Delete one or more bootstrap tokens from the cluster
* [gardenadm token generate](gardenadm_token_generate.md) - Generate a random bootstrap token for joining a node
diff --git a/docs/cli-reference/gardenadm/gardenadm_token_generate.md b/docs/cli-reference/gardenadm/gardenadm_token_generate.md
index 1df4ca87cd3..b6a1ff0a3c9 100644
--- a/docs/cli-reference/gardenadm/gardenadm_token_generate.md
+++ b/docs/cli-reference/gardenadm/gardenadm_token_generate.md
@@ -4,7 +4,7 @@ Generate a random bootstrap token for joining a node
### Synopsis
-Generate a random bootstrap token that can be used for joining a node to an autonomous shoot cluster.
+Generate a random bootstrap token that can be used for joining a node to a self-hosted shoot cluster.
Note that the token is not created on the server (use 'gardenadm token create' for it).
The token is securely generated and follows the format "[a-z0-9]{6}.[a-z0-9]{16}".
Read more about it here: https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/
diff --git a/docs/cli-reference/gardenadm/gardenadm_version.md b/docs/cli-reference/gardenadm/gardenadm_version.md
index 54e63257d4e..b35984da5b1 100644
--- a/docs/cli-reference/gardenadm/gardenadm_version.md
+++ b/docs/cli-reference/gardenadm/gardenadm_version.md
@@ -25,5 +25,5 @@ gardenadm version [flags]
### SEE ALSO
-* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages autonomous shoot clusters in the Gardener project.
+* [gardenadm](gardenadm.md) - gardenadm bootstraps and manages self-hosted shoot clusters in the Gardener project.
diff --git a/docs/concepts/apiserver-admission-plugins.md b/docs/concepts/apiserver-admission-plugins.md
index a181bdd197f..3637aac7fbc 100644
--- a/docs/concepts/apiserver-admission-plugins.md
+++ b/docs/concepts/apiserver-admission-plugins.md
@@ -65,7 +65,7 @@ Usually, regular project members are not bound to this custom verb, allowing the
For `NamespacedCloudProfile`s, the modification of specific fields also require the user to be bound to an RBAC role with custom verbs.
Please see [this document](../usage/project/namespaced-cloud-profiles.md#field-modification-restrictions) for more information.
-For `Shoot`s, the `mark-autonomous` verb is required to set the `spec.provider.workers[].controlPlane` field (which marks a `Shoot` as "autonomous shoot").
+For `Shoot`s, the `mark-self-hosted` verb is required to set the `spec.provider.workers[].controlPlane` field (which marks a `Shoot` as "self-hosted shoot").
## `DeletionConfirmation`
diff --git a/docs/concepts/controller-manager.md b/docs/concepts/controller-manager.md
index 93a6e04342d..d6e3ca1f6c3 100644
--- a/docs/concepts/controller-manager.md
+++ b/docs/concepts/controller-manager.md
@@ -51,9 +51,9 @@ For regular gardenlets managing seed clusters, the controller auto-approves CSRs
1. The CSR matches the requirements for a seed client certificate (correct organization, common name, and usages)
2. The requesting client has permission to create the `certificatesigningrequests/seedclient` subresource
-#### Autonomous Shoot Client Certificates (`shootclient` subresource)
+#### Self-Hosted Shoot Client Certificates (`shootclient` subresource)
-For gardenlets responsible for autonomous shoots, the controller performs additional security validation:
+For gardenlets responsible for self-hosted shoots, the controller performs additional security validation:
1. The CSR must match the requirements for a shoot client certificate (correct organization, common name, and usages)
2. The requesting client must have permission to create the `certificatesigningrequests/shootclient` subresource
3. **Bootstrap Token Validation**: The CSR must be requested via a bootstrap token with a specific description format containing the shoot's namespace and name
@@ -66,7 +66,7 @@ Both types of CSRs rely on the same RBAC setup:
- This ClusterRole grants permission to create both `certificatesigningrequests/seedclient` and `certificatesigningrequests/shootclient` subresources
- The gardenlet's bootstrap kubeconfig contains a bootstrap token that authenticates it as part of the `system:bootstrappers` group
-This dual approval mechanism ensures that both regular seed gardenlets and autonomous shoot gardenlets can obtain client certificates while maintaining appropriate security controls for each deployment model.
+This dual approval mechanism ensures that both regular seed gardenlets and self-hosted shoot gardenlets can obtain client certificates while maintaining appropriate security controls for each deployment model.
### [`CloudProfile` Controller](../../pkg/controllermanager/controller/cloudprofile)
diff --git a/docs/concepts/gardenadm.md b/docs/concepts/gardenadm.md
index 227d6ae406e..f46d8fe6e5d 100644
--- a/docs/concepts/gardenadm.md
+++ b/docs/concepts/gardenadm.md
@@ -1,47 +1,47 @@
---
title: gardenadm
-description: Bootstrapping and management of autonomous shoot clusters.
+description: Bootstrapping and management of self-hosted shoot clusters.
---
> [!CAUTION]
> This tool is currently under development and considered highly experimental.
> Do not use it in production environments.
-> Read more about it in [GEP-28](../proposals/28-autonomous-shoot-clusters.md).
+> Read more about it in [GEP-28](../proposals/28-self-hosted-shoot-clusters.md).
## Overview
-`gardenadm` is a command line tool for bootstrapping Kubernetes clusters called "Autonomous Shoot Clusters".
+`gardenadm` is a command line tool for bootstrapping Kubernetes clusters called "Self-Hosted Shoot Clusters".
In contrast to usual Gardener-managed clusters (called Shoot Clusters), the Kubernetes control plane components run as static pods on a dedicated control plane worker pool in the cluster itself (instead of running them as pods on another Kubernetes cluster (called Seed Cluster)).
-Autonomous shoot clusters can be bootstrapped without an existing Gardener installation.
+Self-hosted shoot clusters can be bootstrapped without an existing Gardener installation.
Hence, they can host a Gardener installation itself and/or serve as the initial seed cluster of a Gardener installation.
-Furthermore, autonomous shoot clusters can only be created by the `gardenadm` tool and not via an API of an existing Gardener system.
+Furthermore, self-hosted shoot clusters can only be created by the `gardenadm` tool and not via an API of an existing Gardener system.

-Such autonomous shoot clusters are meant to operate autonomously, but not to exist completely independently of Gardener.
+Such self-hosted shoot clusters are meant to operate autonomously, but not to exist completely independently of Gardener.
Hence, after their initial creation, they are connected to an existing Gardener system such that the established cluster management functionality via the `Shoot` API can be applied.
-I.e., day-2 operations for autonomous shoot clusters are only supported after connecting them to a Gardener system.
-This Gardener system could also run in an autonomous shoot cluster itself (in this case, you would first need to deploy it before being able to connect the autonomous shoot cluster to it).
+I.e., day-2 operations for self-hosted shoot clusters are only supported after connecting them to a Gardener system.
+This Gardener system could also run in a self-hosted shoot cluster itself (in this case, you would first need to deploy it before being able to connect the self-hosted shoot cluster to it).
-Furthermore, autonomous shoot clusters are not considered a replacement or alternative for regular shoot clusters.
+Furthermore, self-hosted shoot clusters are not considered a replacement or alternative for regular shoot clusters.
They should be only used for special use-cases or requirements as creating them is more complex and as their costs will most likely be higher (since control plane nodes are typically not fully utilized in such architecture).
In this light, a high cluster creation/deletion churn rate is neither expected nor in scope.
## Getting Started Locally
-[This document](../deployment/getting_started_locally_with_gardenadm.md) walks you through deploying Autonomous Shoot Clusters using `gardenadm` on your local machine.
+[This document](../deployment/getting_started_locally_with_gardenadm.md) walks you through deploying Self-Hosted Shoot Clusters using `gardenadm` on your local machine.
This setup can be used for trying out and developing `gardenadm` locally without additional infrastructure.
The setup is also used for running e2e tests for `gardenadm` in CI.
## Scenarios
-We distinguish between two different scenarios for bootstrapping autonomous shoot clusters:
+We distinguish between two different scenarios for bootstrapping self-hosted shoot clusters:
-- High Touch, meaning that there is no programmable infrastructure available.
+- Unmanaged Infrastructure, meaning that there is no programmable infrastructure available.
We consider this the "bare metal" or "edge" use-case, where at first machines must be (often manually) prepared by human operators.
In this case, network setup (e.g., VPCs, subnets, route tables, etc.) and machine management are out of scope.
-- Medium Touch, meaning that there is programmable infrastructure available where we can leverage [provider extensions](../../extensions/README.md#infrastructure-provider) and [`machine-controller-manager`](https://github.com/gardener/machine-controller-manager) in order to manage the network setup and the machines.
+- Managed Infrastructure, meaning that there is programmable infrastructure available where we can leverage [provider extensions](../../extensions/README.md#infrastructure-provider) and [`machine-controller-manager`](https://github.com/gardener/machine-controller-manager) in order to manage the network setup and the machines.
-The general procedure of bootstrapping an autonomous shoot cluster is similar in both scenarios.
+The general procedure of bootstrapping a self-hosted shoot cluster is similar in both scenarios.
diff --git a/docs/deployment/getting_started_locally_with_gardenadm.md b/docs/deployment/getting_started_locally_with_gardenadm.md
index d56e956cf10..924190bcb95 100644
--- a/docs/deployment/getting_started_locally_with_gardenadm.md
+++ b/docs/deployment/getting_started_locally_with_gardenadm.md
@@ -1,11 +1,11 @@
-# Deploying Autonomous Shoot Clusters Locally
+# Deploying Self-Hosted Shoot Clusters Locally
> [!CAUTION]
> The `gardenadm` tool is currently under development and considered highly experimental.
> Do not use it in production environments.
-> Read more about it in [GEP-28](../proposals/28-autonomous-shoot-clusters.md).
+> Read more about it in [GEP-28](../proposals/28-self-hosted-shoot-clusters.md).
-This document walks you through deploying Autonomous Shoot Clusters using `gardenadm` on your local machine.
+This document walks you through deploying Self-Hosted Shoot Clusters using `gardenadm` on your local machine.
This setup can be used for trying out and developing `gardenadm` locally without additional infrastructure.
The setup is also used for running e2e tests for `gardenadm` in CI ([Prow](https://prow.gardener.cloud)).
@@ -13,10 +13,10 @@ If you encounter difficulties, please open an issue so that we can make this pro
## Overview
-`gardenadm` is a command line tool for bootstrapping Kubernetes clusters called "Autonomous Shoot Clusters". Read the [`gardenadm` documentation](../concepts/gardenadm.md) for more details on its concepts.
+`gardenadm` is a command line tool for bootstrapping Kubernetes clusters called "Self-Hosted Shoot Clusters". Read the [`gardenadm` documentation](../concepts/gardenadm.md) for more details on its concepts.
-In this guide, we will start a [KinD](https://kind.sigs.k8s.io/) cluster which hosts pods serving as machines for the autonomous shoot cluster – just as for shoot clusters of [provider-local](../extensions/provider-local.md).
-The setup supports both the high-touch and medium-touch scenario of `gardenadm`.
+In this guide, we will start a [KinD](https://kind.sigs.k8s.io/) cluster which hosts pods serving as machines for the self-hosted shoot cluster – just as for shoot clusters of [provider-local](../extensions/provider-local.md).
+The setup supports both the "unmanaged infrastructure" and the "managed infrastructure" scenario of `gardenadm`.
Based on [Skaffold](https://skaffold.dev/), the container images for all required components will be built and deployed into the cluster.
This also includes the `gardenadm` CLI, which is installed on the machine pods by pulling the container image and extracting the binary.
@@ -44,9 +44,9 @@ All following steps assume that you are using the kubeconfig for this KinD clust
export KUBECONFIG=$PWD/example/gardener-local/kind/multi-zone/kubeconfig
```
-## High-Touch Scenario
+## "Unmanaged Infrastructure" Scenario
-Use the following command to prepare the `gardenadm` high-touch scenario:
+Use the following command to prepare the `gardenadm` unmanaged infrastructure scenario:
```shell
make gardenadm-up
@@ -59,9 +59,9 @@ Afterward, you can use `kubectl exec` to execute `gardenadm` commands on the mac
Let's start with exec'ing into the `machine-0` pod:
```shell
-$ kubectl -n gardenadm-high-touch exec -it machine-0 -- bash
+$ kubectl -n gardenadm-unmanaged-infra exec -it machine-0 -- bash
root@machine-0:/# gardenadm -h
-gardenadm bootstraps and manages autonomous shoot clusters in the Gardener project.
+gardenadm bootstraps and manages self-hosted shoot clusters in the Gardener project.
...
root@machine-0:/# cat /gardenadm/resources/manifests.yaml
@@ -83,13 +83,13 @@ Your Shoot cluster control-plane has initialized successfully!
...
```
-### Connecting to the Autonomous Shoot Cluster
+### Connecting to the Self-Hosted Shoot Cluster
-The machine pod's shell environment is configured for easily connecting to the autonomous shoot cluster.
+The machine pod's shell environment is configured for easily connecting to the self-hosted shoot cluster.
Just execute `kubectl` within a `bash` shell in the machine pod:
```shell
-$ kubectl -n gardenadm-high-touch exec -it machine-0 -- bash
+$ kubectl -n gardenadm-unmanaged-infra exec -it machine-0 -- bash
root@machine-0:/# kubectl get node
NAME STATUS ROLES AGE VERSION
machine-0 Ready 4m11s v1.32.0
@@ -98,8 +98,8 @@ machine-0 Ready 4m11s v1.32.0
You can also copy the kubeconfig to your local machine and use a port-forward to connect to the cluster's API server:
```shell
-$ kubectl -n gardenadm-high-touch exec -it machine-0 -- cat /etc/kubernetes/admin.conf | sed 's/api.root.garden.local.gardener.cloud/localhost:6443/' > /tmp/shoot--garden--root.conf
-$ kubectl -n gardenadm-high-touch port-forward pod/machine-0 6443:443
+$ kubectl -n gardenadm-unmanaged-infra exec -it machine-0 -- cat /etc/kubernetes/admin.conf | sed 's/api.root.garden.local.gardener.cloud/localhost:6443/' > /tmp/shoot--garden--root.conf
+$ kubectl -n gardenadm-unmanaged-infra port-forward pod/machine-0 6443:443
# in a new terminal
$ export KUBECONFIG=/tmp/shoot--garden--root.conf
@@ -117,7 +117,7 @@ Then exec into the `machine-1` pod to run the command:
root@machine-0:/# gardenadm token create --print-join-command
# now copy the output, terminate the exec session and start a new one for machine-1
-$ kubectl -n gardenadm-high-touch exec -it machine-1 -- bash
+$ kubectl -n gardenadm-unmanaged-infra exec -it machine-1 -- bash
# paste the copied 'gardenadm join' command here and execute it
root@machine-1:/# gardenadm join ...
...
@@ -125,7 +125,7 @@ Your node has successfully been instructed to join the cluster as a worker!
...
```
-Using the kubeconfig as described in [this section](#connecting-to-the-autonomous-shoot-cluster), you should now be able to see the new node in the cluster:
+Using the kubeconfig as described in [this section](#connecting-to-the-self-hosted-shoot-cluster), you should now be able to see the new node in the cluster:
```shell
$ kubectl get no
@@ -134,32 +134,32 @@ machine-0 Ready 10m v1.32.0
machine-1 Ready 37s v1.32.0
```
-## Medium-Touch Scenario
+## "Managed Infrastructure" Scenario
-Use the following command to prepare the `gardenadm` medium-touch scenario:
+Use the following command to prepare the `gardenadm` managed infrastructure scenario:
```shell
-make gardenadm-up SCENARIO=medium-touch
+make gardenadm-up SCENARIO=managed-infra
```
-This will first build the needed images and then render the needed manifests for `gardenadm bootstrap` to the [`./dev-setup/gardenadm/resources/generated/medium-touch`](../../dev-setup/gardenadm/resources/generated/medium-touch) directory.
+This will first build the needed images and then render the needed manifests for `gardenadm bootstrap` to the [`./dev-setup/gardenadm/resources/generated/managed-infra`](../../dev-setup/gardenadm/resources/generated/managed-infra) directory.
-### Bootstrapping the Autonomous Shoot Cluster
+### Bootstrapping the Self-Hosted Shoot Cluster
Use `go run` to execute `gardenadm` commands on your machine:
```shell
$ export IMAGEVECTOR_OVERWRITE=$PWD/dev-setup/gardenadm/resources/generated/.imagevector-overwrite.yaml
-$ go run ./cmd/gardenadm bootstrap -d ./dev-setup/gardenadm/resources/generated/medium-touch
+$ go run ./cmd/gardenadm bootstrap -d ./dev-setup/gardenadm/resources/generated/managed-infra
...
[shoot--garden--root-control-plane-58ffc-2l6s7] Your Shoot cluster control-plane has initialized successfully!
...
```
-### Connecting to the Autonomous Shoot Cluster
+### Connecting to the Self-Hosted Shoot Cluster
-`gardenadm init` stores the kubeconfig of the autonomous shoot cluster in the `/etc/kubernetes/admin.conf` file on the control plane machine.
-To connect to the autonomous shoot cluster, set the `KUBECONFIG` environment variable and execute `kubectl` within a `bash` shell in the machine pod:
+`gardenadm init` stores the kubeconfig of the self-hosted shoot cluster in the `/etc/kubernetes/admin.conf` file on the control plane machine.
+To connect to the self-hosted shoot cluster, set the `KUBECONFIG` environment variable and execute `kubectl` within a `bash` shell in the machine pod:
```shell
$ machine="$(kubectl -n shoot--garden--root get po -l app=machine -oname | head -1 | cut -d/ -f2)"
@@ -185,9 +185,9 @@ NAME STATUS ROLES AGE
machine-shoot--garden--root-control-plane-58ffc-2l6s7 Ready 4m11s v1.33.0
```
-## Connecting the Autonomous Shoot Cluster to Gardener
+## Connecting the Self-Hosted Shoot Cluster to Gardener
-After you have successfully bootstrapped an autonomous shoot cluster (either via the [high touch](#high-touch-scenario) or the [medium touch](#medium-touch-scenario) scenario), you can connect it to an existing Gardener system.
+After you have successfully bootstrapped a self-hosted shoot cluster (either via the [unmanaged infrastructure](#unmanaged-infrastructure-scenario) or the [managed infrastructure](#managed-infrastructure-scenario) scenario), you can connect it to an existing Gardener system.
For this, you need to have a Gardener running locally in your KinD cluster.
In order to deploy it, you can run
@@ -199,10 +199,10 @@ This will deploy [`gardener-operator`](../concepts/operator.md) and create a `Ga
Find all information about it [here](getting_started_locally.md#alternative-way-to-set-up-garden-and-seed-leveraging-gardener-operator).
Note, that in this setup, no `Seed` will be registered in the Gardener - it's just a plain garden cluster without the ability to create regular shoot clusters.
-Once above command is finished, you can connect the autonomous shoot cluster to this Gardener instance:
+Once above command is finished, you can connect the self-hosted shoot cluster to this Gardener instance:
```shell
-$ kubectl -n gardenadm-high-touch exec -it machine-0 -- bash
+$ kubectl -n gardenadm-unmanaged-infra exec -it machine-0 -- bash
root@machine-0:/# gardenadm connect
2025-07-03T12:21:49.586Z INFO Command is work in progress
```
@@ -212,13 +212,13 @@ root@machine-0:/# gardenadm connect
Based on the described setup, you can execute the e2e test suite for `gardenadm`:
```shell
-make gardenadm-up SCENARIO=high-touch
+make gardenadm-up SCENARIO=unmanaged-infra
make gardenadm-up SCENARIO=connect
-make test-e2e-local-gardenadm-high-touch
+make test-e2e-local-gardenadm-unmanaged-infra
# or
-make gardenadm-up SCENARIO=medium-touch
-make test-e2e-local-gardenadm-medium-touch
+make gardenadm-up SCENARIO=managed-infra
+make test-e2e-local-gardenadm-managed-infra
```
## Tear Down the KinD Cluster
diff --git a/docs/extensions/provider-local.md b/docs/extensions/provider-local.md
index 4f89c353500..ea959155e1f 100644
--- a/docs/extensions/provider-local.md
+++ b/docs/extensions/provider-local.md
@@ -85,7 +85,7 @@ data:
rewrite stop name regex api.local.local.internal.local.gardener.cloud istio-ingressgateway.istio-ingress.svc.cluster.local answer auto
```
-For autonomous shoots, the controller configures the CoreDNS `template` plugin instead of using a `rewrite` rule for each `DNSRecord`:
+For self-hosted shoots, the controller configures the CoreDNS `template` plugin instead of using a `rewrite` rule for each `DNSRecord`:
```yaml
data:
diff --git a/docs/extensions/registration.md b/docs/extensions/registration.md
index 625a7c12ec9..92580a67360 100644
--- a/docs/extensions/registration.md
+++ b/docs/extensions/registration.md
@@ -275,7 +275,7 @@ In order to allow extension controller deployments to get information about the
gardenlet:
featureGates:
```
-- If the extension is deployed in an [autonomous shoot cluster](../proposals/28-autonomous-shoot-clusters.md), then the `.gardener.autonomousShootCluster` field is additionally propagated and set to `true`.
+- If the extension is deployed in an [self-hosted shoot cluster](../proposals/28-self-hosted-shoot-clusters.md), then the `.gardener.selfHostedShootCluster` field is additionally propagated and set to `true`.
Extension controller deployments can use this information in their Helm chart in case they require knowledge about the garden and the seed environment.
The list might be extended in the future.
diff --git a/docs/extensions/shoot-webhooks.md b/docs/extensions/shoot-webhooks.md
index 053e27f931f..bfa6ac5a171 100644
--- a/docs/extensions/shoot-webhooks.md
+++ b/docs/extensions/shoot-webhooks.md
@@ -22,8 +22,8 @@ The shoot's kube-apiserver must be allowed to talk to the provider extension.
To achieve this, you need to make sure that the relevant `NetworkPolicy` get created for allowing the network traffic.
Please refer to [this guide](../operations/network_policies.md#webhook-servers) for more information.
-## Autonomous Shoot Clusters
+## Self-Hosted Shoot Clusters
-If running in an autonomous shoot cluster, the shoot webhooks should be merged into the seed webhooks.
+If running in a self-hosted shoot cluster, the shoot webhooks should be merged into the seed webhooks.
You can do so by setting the `mergeShootWebhooksIntoSeedWebhooks` to `true` in the `extensions/pkg/webhook/cmd.AddToManager` function.
-Take a look at [this document](registration.md#helm-values) in order to determine whether the extension runs in an autonomous shoot cluster.
+Take a look at [this document](registration.md#helm-values) in order to determine whether the extension runs in a self-hosted shoot cluster.
diff --git a/docs/proposals/28-autonomous-shoot-clusters.md b/docs/proposals/28-self-hosted-shoot-clusters.md
similarity index 84%
rename from docs/proposals/28-autonomous-shoot-clusters.md
rename to docs/proposals/28-self-hosted-shoot-clusters.md
index 5159f6c91eb..cf5e255b8e3 100644
--- a/docs/proposals/28-autonomous-shoot-clusters.md
+++ b/docs/proposals/28-self-hosted-shoot-clusters.md
@@ -1,5 +1,5 @@
---
-title: Autonomous Shoot Clusters
+title: Self-Hosted Shoot Clusters
gep-number: 28
creation-date: 2024-09-17
status: implementable
@@ -9,11 +9,11 @@ authors:
- "@vlerenc"
---
-# GEP-28: Autonomous Shoot Clusters
+# GEP-28: Self-Hosted Shoot Clusters
## Table of Contents
-- [GEP-28: Autonomous Shoot Clusters](#gep-28-autonomous-shoot-clusters)
+- [GEP-28: Self-Hosted Shoot Clusters](#gep-28-self-hosted-shoot-clusters)
- [Table of Contents](#table-of-contents)
- [Summary](#summary)
- [Motivation](#motivation)
@@ -35,19 +35,19 @@ authors:
- [`gardenadm version`](#gardenadm-version)
- [`Shoot` API](#shoot-api)
- [Scenarios](#scenarios)
- - [High Touch](#high-touch)
- - [Medium Touch](#medium-touch)
+ - [Unmanaged Infrastructure](#unmanaged-infrastructure)
+ - [Managed Infrastructure](#managed-infrastructure)
- [`gardenadm bootstrap`](#gardenadm-bootstrap)
- [Disaster Recovery](#disaster-recovery)
- [Single-Node Failure](#single-node-failure)
- [Multi-Node Failure](#multi-node-failure)
- [Data Center Failure](#data-center-failure)
- [Future Work](#future-work)
- - [Autonomous Shoot Clusters for End-Users](#autonomous-shoot-clusters-for-end-users)
+ - [Self-Hosted Shoot Clusters for End-Users](#self-hosted-shoot-clusters-for-end-users)
- [Network Connectivity to Garden Cluster](#network-connectivity-to-garden-cluster)
- [Changes to Shoot Components](#changes-to-shoot-components)
- [Air-Gapped Gardener Landscapes](#air-gapped-gardener-landscapes)
- - [Scaling the Control Plane of Autonomous Shoot Clusters](#scaling-the-control-plane-of-autonomous-shoot-clusters)
+ - [Scaling the Control Plane of Self-Hosted Shoot Clusters](#scaling-the-control-plane-of-self-hosted-shoot-clusters)
- [Alternatives](#alternatives)
- [Using Existing Tools](#using-existing-tools)
- [Using Existing Services](#using-existing-services)
@@ -55,34 +55,34 @@ authors:
## Summary
-Gardener ships with functionality that would allow the creation of "autonomous" shoot clusters.
-Such "autonomous" clusters would be regular shoot clusters with the main difference that their control plane runs on dedicated nodes within the cluster itself (instead of a seed cluster which typically resides in another infrastructure account and network domain).
+Gardener ships with functionality that would allow the creation of "self-hosted" shoot clusters.
+Such "self-hosted" clusters would be regular shoot clusters with the main difference that their control plane runs on dedicated nodes within the cluster itself (instead of a seed cluster which typically resides in another infrastructure account and network domain).
This deployment model is known as the typical/standard Kubernetes deployment model, while Gardener's regular shoot clusters today follow the "Kubeception" deployment model.

> [!IMPORTANT]
> This shall not be a drop-in replacement for [`k3s`](https://k3s.io) or [`kubeadm`](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm) (that would be too far away from Gardener's mission statement, TCO goals, and current implementation), but we want to offer this new type of shoot clusters as a separate flavor to enable on-prem use-cases that cannot be served with Gardener today.
-> By allowing the remote management through Gardener, "autonomous" clusters will meet our mission statement (e.g., in regards to low TCO) while operating without the need of a seed cluster.
+> By allowing the remote management through Gardener, "self-hosted" clusters will meet our mission statement (e.g., in regard to low TCO) while operating without the need of a seed cluster.
-Such autonomous shoot clusters are meant to operate autonomously, but not to exist completely independently of Gardener.
+Such self-hosted shoot clusters are meant to operate autonomously, but not to exist completely independently of Gardener.
Hence, after initial creation, they shall be connected to an existing Gardener system such that the established cluster management functionality via the `Shoot` API can be applied.
-Furthermore, autonomous shoot clusters are not considered a replacement or alternative for regular shoot clusters.
+Furthermore, self-hosted shoot clusters are not considered a replacement or alternative for regular shoot clusters.
They should be only used for special use-cases or requirements as their creation time will be longer and their costs will be higher.
In this light, a high cluster creation/deletion churn rate is neither expected nor in scope.
Gardener's APIs and cluster topology are defined in a way such that seed clusters are a separate "security domain" and not accessible to end-users.
-With autonomous shoot clusters, seed clusters do not exist anymore, hence, running a `gardenlet` and certain seed system components (like extensions) within the end-user's infrastructure requires rework and adaptation of some of today's concepts.
-As operating autonomous shoot clusters is a challenge big enough on its own, we'll start with focusing only on how Gardener operators can create and connect autonomous shoot clusters.
-Allowing "untrusted" end-users to create such clusters is out of scope of this GEP and considered to be future work ([see below](#autonomous-shoot-clusters-for-end-users)).
+With self-hosted shoot clusters, seed clusters do not exist anymore, hence, running a `gardenlet` and certain seed system components (like extensions) within the end-user's infrastructure requires rework and adaptation of some of today's concepts.
+As operating self-hosted shoot clusters is a challenge big enough on its own, we'll start with focusing only on how Gardener operators can create and connect self-hosted shoot clusters.
+Allowing "untrusted" end-users to create such clusters is out of scope of this GEP and considered to be future work ([see below](#self-hosted-shoot-clusters-for-end-users)).
## Motivation
Gardener is a great tool for creating and managing clusters with very low TCO.
Part of this success is its architecture, i.e., running control planes in seed clusters under joint supervision by Gardener and Kubernetes (a.k.a. Kubeception deployment model).
-However, there is sufficient pull to also find a way to create autonomous shoot clusters using Gardener (e.g., for the edge or for temporarily air-gapped scenarios) where the control plane must run side-by-side and cannot run in seed clusters.
+However, there is sufficient pull to also find a way to create self-hosted shoot clusters using Gardener (e.g., for the edge or for temporarily air-gapped scenarios) where the control plane must run side-by-side and cannot run in seed clusters.
We want to establish Gardener in (new) environments where clusters cannot run their control plane "somewhere else", but where it needs to be co-located with the worker nodes, e.g., to avoid costly or exposed network traffic, firewall the entire cluster off, rely on the control plane while the cluster is air-gapped/has no internet access, generally avoid runtime dependencies, fulfill compliance obligations, etc.
In addition, Gardener itself requires to run in a conformant Kubernetes cluster satisfying the [minimum Kubernetes version requirements](../usage/shoot-operations/supported_k8s_versions.md#garden-clusters), but so far there was no way of setting up or managing this initial cluster via Gardener itself.
@@ -91,20 +91,20 @@ Augmenting Gardener's capability to also manage the initial cluster will help to
### Goals
-- Creation of autonomous shoot clusters running dedicated nodes for control plane components
+- Creation of self-hosted shoot clusters running dedicated nodes for control plane components
- Maximize re-use of existing code/functionality to prevent re-inventing the wheel
- Enable cluster management and upgrades via the `Shoot` API of an existing Gardener
### Non-Goals
-- Creation/deletion of autonomous shoot clusters with high churn rates and convenience compared to regular shoot clusters
-- Allow end-users to create autonomous shoot clusters and connect them to a Gardener system - this aspect will be covered in a future GEP after this one has been implemented
-- Provide functionality to create autonomous shoot clusters via the API of an existing Gardener system
+- Creation/deletion of self-hosted shoot clusters with high churn rates and convenience compared to regular shoot clusters
+- Allow end-users to create self-hosted shoot clusters and connect them to a Gardener system - this aspect will be covered in a future GEP after this one has been implemented
+- Provide functionality to create self-hosted shoot clusters via the API of an existing Gardener system
- Support day-2 operations without connecting the cluster to an existing Gardener system
## Proposal
-In short, the basic idea is to develop a new command line tool that is going to be shipped with every Gardener release, `gardenadm`, which can be used to bootstrap an autonomous shoot cluster.
+In short, the basic idea is to develop a new command line tool that is going to be shipped with every Gardener release, `gardenadm`, which can be used to bootstrap a self-hosted shoot cluster.
@@ -129,17 +129,17 @@ Similar to [`kubeadm`'s prerequisites](https://kubernetes.io/docs/setup/producti
`gardenadm` will have the following commands:
-- [`gardenadm discover`](#gardenadm-discover) to discover the configuration of the Gardener system the autonomous shoot cluster shall be connected to later.
+- [`gardenadm discover`](#gardenadm-discover) to discover the configuration of the Gardener system the self-hosted shoot cluster shall be connected to later.
- [`gardenadm init`](#gardenadm-init) to bootstrap a first control plane node.
- [`gardenadm token`](#gardenadm-token) to manage bootstrap and discovery tokens for `gardenadm join`.
- [`gardenadm join`](#gardenadm-join) to bootstrap further control plane nodes, or to bootstrap worker nodes and join them to the cluster.
- [`gardenadm connect`](#gardenadm-connect) to deploy a `gardenlet` for further cluster management.
- [`gardenadm version`](#gardenadm-version) to print the `gardenadm` version.
-The general flow for bootstrapping an autonomous shoot cluster will be as follows:
+The general flow for bootstrapping a self-hosted shoot cluster will be as follows:
1. The user installs `gardenadm` on the first control plane node and runs `gardenadm discover`.
- This will download relevant configuration from the Gardener system the autonomous shoot cluster shall be later connected to (e.g., `Controller{Registration,Deployment}`s, `CloudProfile`s, etc.).
+ This will download relevant configuration from the Gardener system the self-hosted shoot cluster shall be later connected to (e.g., `Controller{Registration,Deployment}`s, `CloudProfile`s, etc.).
If there is no existing Gardener system yet, the needed configuration must be provided manually.
2. The downloaded configuration and a `Shoot` manifest are provided to the `gardenadm init` command.
This will bootstrap the first control plane node.
@@ -156,11 +156,11 @@ A more detailed description of the commands is following.
This command takes a kubeconfig to an existing Gardener system, and a `Shoot` manifest.
It downloads the required `CloudProfile`, `ControllerRegistration` and `ControllerDeployment` resources and stores them locally for usage of other `gardenadm` commands.
-This simplifies the crafting of these documents, and it also ensures that the configuration and versions used for the bootstrapping of the autonomous shoot cluster fit to the configuration later found in the connected Gardener system.
+This simplifies the crafting of these documents, and it also ensures that the configuration and versions used for the bootstrapping of the self-hosted shoot cluster fit to the configuration later found in the connected Gardener system.
#### `gardenadm init`
-This command bootstraps the first control plane node of the autonomous shoot cluster.
+This command bootstraps the first control plane node of the self-hosted shoot cluster.
The configuration is specified via separate files.
It needs a `Shoot` manifest and some additional configuration files, which usually reside in the garden cluster, e.g., a `CloudProfile` (best downloaded with `gardenadm discover`).
For the initial cluster Gardener bootstrapping use-case however, these won't come from a pre-existing garden cluster as it doesn't exist yet.
@@ -244,7 +244,7 @@ The static pod manifest can then be exchanged on the host and replace the "boots
> [!NOTE]
> At the time of writing this GEP, it is not yet fully clear how/whether this approach fits into the design plans for `etcd-druid`.
-> An alternative idea is to make `etcd-druid` aware of the concept of autonomous shoot clusters and give it further control into the management of static `etcd` pods.
+> An alternative idea is to make `etcd-druid` aware of the concept of self-hosted shoot clusters and give it further control into the management of static `etcd` pods.
> The details are still subject to discussion and will become clearer in the future.
> Since we need a "bootstrap `etcd`" anyway to get the cluster up and running, we can proceed with this GEP and its implementation in parallel while the discussion around how `etcd-druid` can take over the management is ongoing.
@@ -290,16 +290,16 @@ Apart from this, `etcd` also needs to be re-configured to have the new node join
#### `gardenadm connect`
-This command deploys a `gardenlet` into the autonomous shoot cluster and connects it to an existing garden cluster.
+This command deploys a `gardenlet` into the self-hosted shoot cluster and connects it to an existing garden cluster.
As part of this operation, the corresponding `Shoot` resource will be created in the garden cluster.
-Afterwards, the `gardenlet` will reconcile the autonomous shoot cluster similarly to regular shoot clusters.
+Afterwards, the `gardenlet` will reconcile the self-hosted shoot cluster similarly to regular shoot clusters.
> [!NOTE]
-> When there is no existing Gardener system yet (for example, because the created autonomous shoot cluster is the initial cluster), then [`gardener-operator`](../concepts/operator.md) must be deployed first, and the [`Garden`](../../example/operator/20-garden.yaml) must be created, before the `gardenlet` can be deployed.
+> When there is no existing Gardener system yet (for example, because the created self-hosted shoot cluster is the initial cluster), then [`gardener-operator`](../concepts/operator.md) must be deployed first, and the [`Garden`](../../example/operator/20-garden.yaml) must be created, before the `gardenlet` can be deployed.
>
-> Also, it is not yet clear whether the existing `gardenlet` binary will be re-used, or whether we better create a dedicated, new binary with slimmed down functionality catered for only managing autonomous shoot clusters.
+> Also, it is not yet clear whether the existing `gardenlet` binary will be re-used, or whether we better create a dedicated, new binary with slimmed down functionality catered for only managing self-hosted shoot clusters.
-Depending on the scenario, an autonomous shoot cluster may be air-gapped for periods of time.
+Depending on the scenario, a self-hosted shoot cluster may be air-gapped for periods of time.
Therefore, please note that the cluster should function also when air-gapped/when it has limited or no network connectivity.
Updates can not be performed during that time, but ordinary operations with the cluster itself (e.g., creating pods or services) should still be possible.
It is important that the [version skew](../deployment/version_skew_policy.md) is always respected.
@@ -310,7 +310,7 @@ This command prints the version of `gardenadm`.
### `Shoot` API
-We need some mechanism to distinguish regular shoot clusters from autonomous shoot clusters.
+We need some mechanism to distinguish regular shoot clusters from self-hosted shoot clusters.
As the most prominent difference is that there are dedicated machines for the control plane components, we propose to notice the difference based on the existence of a worker pool for the control plane:
```yaml
@@ -327,14 +327,14 @@ An alternative is to augment `.spec.controlPlane` with this information, however
We distinguish between two different scenarios (for now):
-- [High Touch](#high-touch), meaning that there is no programmable infrastructure available.
+- [Unmanaged Infrastructure](#unmanaged-infrastructure), meaning that there is no programmable infrastructure available.
We consider this the "bare metal" or "edge" use-case, where at first machines must be (often manually) prepared by human operators.
In this case, network setup (e.g., VPCs, subnets, route tables, etc.) and machine management are out of scope.
-- [Medium Touch](#medium-touch), meaning that there is programmable infrastructure available where we can leverage [provider extensions](../../extensions/README.md#infrastructure-provider) and [`machine-controller-manager`](https://github.com/gardener/machine-controller-manager) in order to manage the network setup and the machines.
+- [Managed Infrastructure](#managed-infrastructure), meaning that there is programmable infrastructure available where we can leverage [provider extensions](../../extensions/README.md#infrastructure-provider) and [`machine-controller-manager`](https://github.com/gardener/machine-controller-manager) in order to manage the network setup and the machines.
-The general procedure of bootstrapping an autonomous shoot cluster is similar in both scenarios.
+The general procedure of bootstrapping a self-hosted shoot cluster is similar in both scenarios.
-#### High Touch
+#### Unmanaged Infrastructure
In this scenario, the starting point is right on the first machine that shall be transformed into a control plane node.
It is assumed that the network was set up properly (see [Prerequisites](#prerequisites)).
@@ -342,15 +342,15 @@ Since machine management is out of scope, upgrades requiring to roll out the nod
We will leverage the functionality that is to be developed in the scope of [#10219](https://github.com/gardener/gardener/issues/10219).
This will also include operating system upgrades [planned for Garden Linux](https://github.com/gardener/gardener/issues/10219#issuecomment-2262299606).
-#### Medium Touch
+#### Managed Infrastructure
In this scenario, we can leverage the existing [`extensions.gardener.cloud/v1alpha1.Infrastructure` API](../extensions/resources/infrastructure.md) in order to let the respective provider extension generate the necessary network resources (VPCs, subnets, etc., whatever is needed for the respective infrastructure).
-`machine-controller-manager` can be used to create the control plane nodes (and later also the worker nodes) of the autonomous shoot cluster.
+`machine-controller-manager` can be used to create the control plane nodes (and later also the worker nodes) of the self-hosted shoot cluster.
The challenge is that both Gardener provider extensions and `machine-controller-manager` depend on a pre-existing Kubernetes cluster or in general an API server.
Hence, we propose to use a [KinD cluster](https://kind.sigs.k8s.io), deploy the needed components into it, and create the necessary `Infrastructure`, `MachineClass`, and `MachineDeployment` resources.
This way, these components can be reused as-is, without big changes or re-wiring of these complex components to run in-process with a fake client (as we do during the `gardenadm init` flow for the simpler components).
-Once the controllers have reconciled successfully, we can export the created infrastructure state and the `Machine` resources, bootstrap the autonomous shoot cluster similar to the [general flow](#commands) also needed for the [High Touch scenario](#high-touch), and import the state again into the created cluster.
+Once the controllers have reconciled successfully, we can export the created infrastructure state and the `Machine` resources, bootstrap the self-hosted shoot cluster similar to the [general flow](#commands) also needed for the [Unmanaged Infrastructure scenario](#unmanaged-infrastructure), and import the state again into the created cluster.
There is no special assumption about the location of the KinD cluster.
It should run somewhere where it can access the API of the target infrastructure.
@@ -368,8 +368,8 @@ Since we assume that this scenario will be the prominent one, we plan to add ano
##### `gardenadm bootstrap`
-This command creates the virtual network and machines to be used for the control plane of the autonomous shoot cluster.
-It uses an existing KinD cluster to temporarily deploy existing Gardener components (unaware of the autonomous shoot cluster use-case).
+This command creates the virtual network and machines to be used for the control plane of the self-hosted shoot cluster.
+It uses an existing KinD cluster to temporarily deploy existing Gardener components (unaware of the self-hosted shoot cluster use-case).
These components, such as provider extensions and `machine-controller-manager`, are used to create the necessary infrastructure and machines.
The high-level steps are as follows:
@@ -384,7 +384,7 @@ The high-level steps are as follows:
8. Create a `Bastion` resource to be able to access the machines and execute `gardenadm init` (can be later optimized via `cloud-init` through a cloud config that invokes `gardenadm init` directly when creating the machines).
The states of the `Infrastructure` and `Machine` resources need to be exported from the KinD cluster.
-Once the autonomous shoot cluster control plane is running, the state should be imported so that it can be managed by the provider extension and `machine-controller-manager` respectively.
+Once the self-hosted shoot cluster control plane is running, the state should be imported so that it can be managed by the provider extension and `machine-controller-manager` respectively.
The KinD cluster can be deleted afterwards.
@@ -392,7 +392,7 @@ The KinD cluster can be deleted afterwards.
Disasters can strike in many different ways.
This section discusses disasters in ascending order of severity.
-Some scenarios can be handled by autonomous shoot clusters automatically, others require manual intervention.
+Some scenarios can be handled by self-hosted shoot clusters automatically, others require manual intervention.
#### Single-Node Failure
@@ -433,59 +433,59 @@ The resolution/handling of data center failures is out of scope of this GEP.
## Future Work
-### Autonomous Shoot Clusters for End-Users
+### Self-Hosted Shoot Clusters for End-Users
-As implicitly mentioned in the [Non-Goals](#non-goals) section, the focus of this GEP is to allow Gardener operators to create autonomous shoot clusters.
+As implicitly mentioned in the [Non-Goals](#non-goals) section, the focus of this GEP is to allow Gardener operators to create self-hosted shoot clusters.
However, the creation of such clusters by end-users is not covered by this GEP.
This could become a future topic if we consider it relevant enough.
-Handling creation of autonomous shoot clusters by end-users requires refined access controls for the `gardenlet`.
+Handling creation of self-hosted shoot clusters by end-users requires refined access controls for the `gardenlet`.
Currently, the `gardenlet` runs as part of a seed cluster and has access to some resources, which are not accessible to end-users but only to operators.
An example resource is the `ControllerDeployment`, which may contain credentials, e.g., for certificate management or domain name services.
In case this scenario is desired and the security boundary between Gardener operators and end-users should stay as is, the extension deployment needs to be adapted.
-While it may be appealing to have support for autonomous shoot cluster for end-users, it is important to understand that this feature may complicate the world for both operators and end-users.
-The benefits of autonomous shoot clusters for the garden runtime cluster and/or soil clusters, i.e., unmanaged seed clusters, is fairly obvious:
+While it may be appealing to have support for self-hosted shoot cluster for end-users, it is important to understand that this feature may complicate the world for both operators and end-users.
+The benefits of self-hosted shoot clusters for the garden runtime cluster and/or soil clusters, i.e., unmanaged seed clusters, is fairly obvious:
It allows to create a Gardener landscape without external dependency to a Kubernetes service provider.
However, the benefits for end-users are less clear (except for the mentioned edge/on-prem/air-gapped use cases).
-It needs to be carefully considered and documented for what scenarios autonomous shoot clusters are the right choice, and when ordinary shoot clusters with their control plane running on a seed cluster are the better way to go.
+It needs to be carefully considered and documented for what scenarios self-hosted shoot clusters are the right choice, and when ordinary shoot clusters with their control plane running on a seed cluster are the better way to go.
Without this consideration, the feature may increase the operational complexity for Gardener operators, and the cognitive load for end-users.
### Network Connectivity to Garden Cluster
-Another aspect that was only barely touched in this GEP is the reliability of the network connectivity between the autonomous shoot cluster and Gardener.
+Another aspect that was only barely touched in this GEP is the reliability of the network connectivity between the self-hosted shoot cluster and Gardener.
In the [`gardenadm connect` section](#gardenadm-connect), it was mentioned that the cluster should function also when air-gapped/when it has limited or no network connectivity.
However, we are deliberately vague what "limited network connectivity" means.
Detailing this aspect out can be considered future work.
-As mentioned in the corresponding section, the [version skew](../deployment/version_skew_policy.md) plays an important role in this context, determining the maximum time the autonomous shoot cluster can be disconnected from Gardener.
+As mentioned in the corresponding section, the [version skew](../deployment/version_skew_policy.md) plays an important role in this context, determining the maximum time the self-hosted shoot cluster can be disconnected from Gardener.
Long term support of Gardener and associated components may also be considered future work.
### Changes to Shoot Components
-Due to the changed network layout of autonomous shoot clusters, the usage of some shoot components needs to be reconsidered.
+Due to the changed network layout of self-hosted shoot clusters, the usage of some shoot components needs to be reconsidered.
Examples are the VPN connection between control plane and data plane, the `apiserver-proxy` and the way metrics are scraped.
This GEP does not cover these changes in detail, but they are important to be considered when implementing it.
The following examples are just used to illustrate the need for changes, but are not meant to be exhaustive:
- The VPN connection between control plane and data plane is not needed anymore as the control plane runs on the same network as the data plane.
Previously, the VPN connection was used to secure the communication between the control plane and the data plane.
This was important as the control plane and the data plane were running in different networks with a potentially untrusted network in between.
-In the autonomous shoot cluster scenario, this is no longer the case.
+In the self-hosted shoot cluster scenario, this is no longer the case.
The control plane can directly communicate with the data plane without the need for a VPN connection.
- The `apiserver-proxy` (see [GEP-11](11-apiserver-network-proxy.md) for details) is used to forward requests from the data plane directed at `kubernetes.default.svc.cluster.local` to the control plane.
- In the autonomous shoot cluster scenario, this can be simplified by directly pointing `kubernetes.default.svc.cluster.local` to the actual endpoints of the `kube-apiserver`.
+ In the self-hosted shoot cluster scenario, this can be simplified by directly pointing `kubernetes.default.svc.cluster.local` to the actual endpoints of the `kube-apiserver`.
This way, the `apiserver-proxy` is no longer needed.
- Another aspect is the [mutating webhook for injecting the `KUBERNETES_SERVICE_HOST` environment variable](../concepts/resource-manager.md#kubernetes-service-host-injection), which can be disabled in the autonomous shoot cluster scenario as well.
+ Another aspect is the [mutating webhook for injecting the `KUBERNETES_SERVICE_HOST` environment variable](../concepts/resource-manager.md#kubernetes-service-host-injection), which can be disabled in the self-hosted shoot cluster scenario as well.
- In ordinary shoot clusters, the metrics of components running in the data plane are scraped indirectly via the `kube-apiserver`.
This allows the observability stack to use the VPN connection without explicitly configuring it.
- As stated above, the VPN connection is no longer needed in the autonomous shoot cluster scenario.
+ As stated above, the VPN connection is no longer needed in the self-hosted shoot cluster scenario.
Therefore, the observability stack could also directly scrape metrics from the data plane components instead of going through the `kube-apiserver`.
There may be other components, which are affected by the changed network layout and need to be adapted.
### Air-Gapped Gardener Landscapes
-While it is already possible today to run a Gardener landscape in an air-gapped environment, the autonomous shoot cluster feature will make it easier to set up such a landscape.
+While it is already possible today to run a Gardener landscape in an air-gapped environment, the self-hosted shoot cluster feature will make it easier to set up such a landscape.
This is due to the fact that it removes the dependency on an external Kubernetes cluster to run the Garden and act as the initial seed cluster.
Therefore, it may be worthwhile to take a closer look at the requirements for air-gapped Gardener landscapes and document them properly.
@@ -498,12 +498,12 @@ Topics to consider (without any claim of completeness) are:
The goal would be to provide a comprehensive guide on how to set up an air-gapped Gardener landscape, which can be applied on various infrastructures.
It may also be useful for scenarios that are not fully air-gapped, but only desire selected parts of the sovereignty this provides.
-### Scaling the Control Plane of Autonomous Shoot Clusters
+### Scaling the Control Plane of Self-Hosted Shoot Clusters
The control plane components of ordinary Gardener shoot clusters are scaled horizontally and vertically in various ways.
Autoscaling is not covered in this GEP, but it is important in the long run to ensure efficient resource usage.
-As far as this GEP is concerned, the control plane of autonomous shoot clusters is scaled horizontally by adding more control plane nodes (see [`gardenadm join`](#gardenadm-join)).
+As far as this GEP is concerned, the control plane of self-hosted shoot clusters is scaled horizontally by adding more control plane nodes (see [`gardenadm join`](#gardenadm-join)).
This approach can be problematic in various ways.
As this GEP proposes to always deploy the full set of default control plane components on each control plane node, there may be more instances running for `kube-scheduler` and `kube-controller-manager` than practically necessary.
@@ -511,7 +511,7 @@ While this may be a good approach in scaling `kube-apiserver` horizontally, it m
Furthermore, from `etcd`'s perspective the amount of control plane nodes should ideally be odd and no more than seven (see [etcd faq](https://etcd.io/docs/v3.4/faq/)).
This further limits the scalability of the control plane.
-Therefore, it may be a good idea to investigate how node roles can help improve efficiency in a scale-out autonomous shoot cluster scenario.
+Therefore, it may be a good idea to investigate how node roles can help improve efficiency in a scale-out self-hosted shoot cluster scenario.
Some control plane nodes could include the full set of default control plane components while others may use a reduced set of components.
This could be achieved by having roles for either individual components or different set of components.
@@ -522,14 +522,14 @@ Yet another option in the contrary direction would be to allow non-control plane
This would allow to use the control plane nodes to their full capacity, but it would also blur the separation between control and data plane nodes.
While it may improve the resource utilisation of control plane nodes, it may also introduce security risks.
-In any case, revisiting the scaling problem is required to ensure efficient resource usage with growing control plane usage in the context of autonomous shoot clusters.
+In any case, revisiting the scaling problem is required to ensure efficient resource usage with growing control plane usage in the context of self-hosted shoot clusters.
## Alternatives
### Using Existing Tools
Existing tools, e.g., [`k3s`](https://k3s.io) or [`kubeadm`](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm), could be used to create the initial Kubernetes cluster.
-This cluster could then be "adopted" by Gardener and managed by the `gardenlet` as described for the day-2 operations in the autonomous shoot cluster case.
+This cluster could then be "adopted" by Gardener and managed by the `gardenlet` as described for the day-2 operations in the self-hosted shoot cluster case.
It was deemed much more complex to align a cluster created by a third-party tool with Gardener's expectations than to create the cluster directly with Gardener.
The fact that these tools evolve independently from Gardener and may introduce breaking changes was another reason to prefer the direct creation with Gardener.
@@ -542,7 +542,7 @@ For example, it may be undesirable/impossible for an air-gapped environment to h
### Using Existing Gardener
-Using an existing Gardener to create an autonomous cluster is an option, yet it requires a more complex satisfaction of prerequisites to make this approach work.
+Using an existing Gardener to create a self-hosred cluster is an option, yet it requires a more complex satisfaction of prerequisites to make this approach work.
For example, network connectivity from a seed cluster (where extensions and a `gardenlet` runs) to the target infrastructure must exist.
When the initial cluster shall be created, pivoting from a local KinD cluster can be an option, but it also requires to solve the challenge of migrating the Gardener control plane.
In summary, we considered this approach more complex to develop and use.
diff --git a/example/90-shoot.yaml b/example/90-shoot.yaml
index 76fe6d25028..db868ebb9bb 100644
--- a/example/90-shoot.yaml
+++ b/example/90-shoot.yaml
@@ -150,7 +150,7 @@ spec:
# sysctls: # optional, allows to specify kernel settings to override defaults
# net.ipv4.tcp_wmem: "4096 131072 16777216"
# net.ipv4.tcp_rmem: "4096 131072 16777216"
- # controlPlane: # mark the shoot as "autonomous shoot cluster", see GEP-28
+ # controlPlane: # mark the shoot as "self-hosted shoot cluster", see GEP-28
# backup:
# provider: # e.g., aws, azure, gcp, ...
# providerConfig:
diff --git a/extensions/pkg/controller/cmd/options.go b/extensions/pkg/controller/cmd/options.go
index 58e282aeb17..c5703d13202 100644
--- a/extensions/pkg/controller/cmd/options.go
+++ b/extensions/pkg/controller/cmd/options.go
@@ -66,9 +66,9 @@ const (
// GardenerVersionFlag is the name of the command line flag containing the Gardener version.
GardenerVersionFlag = "gardener-version"
- // AutonomousShootClusterFlag is the name of the command line flag indicating that the extension runs in an
- // autonomous shoot cluster.
- AutonomousShootClusterFlag = "autonomous-shoot-cluster"
+ // SelfHostedShootClusterFlag is the name of the command line flag indicating that the extension runs in a
+ // self-hosted shoot cluster.
+ SelfHostedShootClusterFlag = "self-hosted-shoot-cluster"
// LogLevelFlag is the name of the command line flag containing the log level.
LogLevelFlag = "log-level"
@@ -479,8 +479,8 @@ type SwitchConfig struct {
type GeneralOptions struct {
// GardenerVersion is the version of the Gardener.
GardenerVersion string
- // AutonomousShootCluster indicates whether the extension runs in an autonomous shoot cluster.
- AutonomousShootCluster bool
+ // SelfHostedShootCluster indicates whether the extension runs in a self-hosted shoot cluster.
+ SelfHostedShootCluster bool
config *GeneralConfig
}
@@ -489,13 +489,13 @@ type GeneralOptions struct {
type GeneralConfig struct {
// GardenerVersion is the version of the Gardener.
GardenerVersion string
- // AutonomousShootCluster indicates whether the extension runs in an autonomous shoot cluster.
- AutonomousShootCluster bool
+ // SelfHostedShootCluster indicates whether the extension runs in a self-hosted shoot cluster.
+ SelfHostedShootCluster bool
}
// Complete implements Complete.
func (r *GeneralOptions) Complete() error {
- r.config = &GeneralConfig{r.GardenerVersion, r.AutonomousShootCluster}
+ r.config = &GeneralConfig{r.GardenerVersion, r.SelfHostedShootCluster}
return nil
}
@@ -507,5 +507,5 @@ func (r *GeneralOptions) Completed() *GeneralConfig {
// AddFlags implements Flagger.AddFlags.
func (r *GeneralOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&r.GardenerVersion, GardenerVersionFlag, "", "Version of the gardenlet.")
- fs.BoolVar(&r.AutonomousShootCluster, AutonomousShootClusterFlag, false, "Does the extension run in an autonomous shoot cluster?")
+ fs.BoolVar(&r.SelfHostedShootCluster, SelfHostedShootClusterFlag, false, "Does the extension run in a self-hosted shoot cluster?")
}
diff --git a/extensions/pkg/controller/controlplane/genericactuator/actuator.go b/extensions/pkg/controller/controlplane/genericactuator/actuator.go
index 9465bc76b54..502442e3889 100644
--- a/extensions/pkg/controller/controlplane/genericactuator/actuator.go
+++ b/extensions/pkg/controller/controlplane/genericactuator/actuator.go
@@ -419,7 +419,7 @@ func (a *actuator) delete(ctx context.Context, log logr.Logger, cp *extensionsv1
}
func (a *actuator) hasShootWebhooks(shoot *gardencorev1beta1.Shoot) bool {
- return a.atomicShootWebhookConfig != nil && !v1beta1helper.IsShootAutonomous(shoot.Spec.Provider.Workers)
+ return a.atomicShootWebhookConfig != nil && !v1beta1helper.IsShootSelfHosted(shoot.Spec.Provider.Workers)
}
// computeChecksums computes and returns all needed checksums. This includes the checksums for the given deployed secrets,
diff --git a/extensions/pkg/controller/worker/controller.go b/extensions/pkg/controller/worker/controller.go
index f8b2e126c1b..b4c850562c7 100644
--- a/extensions/pkg/controller/worker/controller.go
+++ b/extensions/pkg/controller/worker/controller.go
@@ -53,8 +53,8 @@ type AddArgs struct {
IgnoreOperationAnnotation bool
// ExtensionClass defines the extension class this extension is responsible for.
ExtensionClass extensionsv1alpha1.ExtensionClass
- // AutonomousShootCluster indicates whether the extension runs in an autonomous shoot cluster.
- AutonomousShootCluster bool
+ // SelfHostedShootCluster indicates whether the extension runs in a self-hosted shoot cluster.
+ SelfHostedShootCluster bool
}
// DefaultPredicates returns the default predicates for a Worker reconciler.
@@ -81,7 +81,7 @@ func Add(ctx context.Context, mgr manager.Manager, args AddArgs) error {
return err
}
- if mustWatchMachines, err := wantMachineWatch(args.AutonomousShootCluster, mgr.GetRESTMapper()); err != nil {
+ if mustWatchMachines, err := wantMachineWatch(args.SelfHostedShootCluster, mgr.GetRESTMapper()); err != nil {
return fmt.Errorf("failed to determine if machine API exists: %w", err)
} else if mustWatchMachines {
if err := c.Watch(source.Kind[client.Object](
@@ -109,8 +109,8 @@ func Add(ctx context.Context, mgr manager.Manager, args AddArgs) error {
return nil
}
-func wantMachineWatch(isAutonomousShootCluster bool, restMapper meta.RESTMapper) (bool, error) {
- if !isAutonomousShootCluster {
+func wantMachineWatch(isSelfHostedShootCluster bool, restMapper meta.RESTMapper) (bool, error) {
+ if !isSelfHostedShootCluster {
return true, nil
}
return machineAPIPresent(restMapper)
diff --git a/hack/ci-e2e-kind-gardenadm.sh b/hack/ci-e2e-kind-gardenadm.sh
index ed83fa81bcb..03981316cf3 100755
--- a/hack/ci-e2e-kind-gardenadm.sh
+++ b/hack/ci-e2e-kind-gardenadm.sh
@@ -21,26 +21,26 @@ trap "
( make kind-single-node-down )
" EXIT
-# medium-touch tests cannot run when there is a gardener-operator deployment (i.e., high-touch/connect tests must run
-# separately). Hence, let's run the medium-touch tests first, then clean them up, and then run the high-touch/connect
+# managed-infra tests cannot run when there is a gardener-operator deployment (i.e., unmanaged-infra/connect tests must run
+# separately). Hence, let's run the managed-infra tests first, then clean them up, and then run the unmanaged-infra/connect
# tests.
-# medium-touch
+# managed infrastructure
make kind-single-node-up
-make gardenadm-up SCENARIO=medium-touch
+make gardenadm-up SCENARIO=managed-infra
-make test-e2e-local-gardenadm-medium-touch
+make test-e2e-local-gardenadm-managed-infra
-make gardenadm-down SCENARIO=medium-touch
+make gardenadm-down SCENARIO=managed-infra
make kind-single-node-down
-# high touch
+# unmanaged infrastructure
make kind-single-node-up
-make gardenadm-up SCENARIO=high-touch
+make gardenadm-up SCENARIO=unmanaged-infra
make gardenadm-up SCENARIO=connect
-make test-e2e-local-gardenadm-high-touch
+make test-e2e-local-gardenadm-unmanaged-infra
make gardenadm-down SCENARIO=connect
-make gardenadm-down SCENARIO=high-touch
+make gardenadm-down SCENARIO=unmanaged-infra
make kind-single-node-down
diff --git a/pkg/admissioncontroller/gardenletidentity/shoot/identity.go b/pkg/admissioncontroller/gardenletidentity/shoot/identity.go
index b02d8795cac..749c9aee921 100644
--- a/pkg/admissioncontroller/gardenletidentity/shoot/identity.go
+++ b/pkg/admissioncontroller/gardenletidentity/shoot/identity.go
@@ -18,8 +18,8 @@ import (
)
// FromUserInfoInterface returns the shoot namespace and name, a boolean indicating whether the provided user is an
-// autonomous shoot client, and the client's UserType.
-func FromUserInfoInterface(u user.Info) (namespace string, name string, isAutonomousShoot bool, userType gardenletidentity.UserType) {
+// self-hosted shoot client, and the client's UserType.
+func FromUserInfoInterface(u user.Info) (namespace string, name string, isSelfHostedShoot bool, userType gardenletidentity.UserType) {
if u == nil {
return "", "", false, ""
}
@@ -37,7 +37,7 @@ func FromUserInfoInterface(u user.Info) (namespace string, name string, isAutono
// FromAuthenticationV1UserInfo converts an authenticationv1.UserInfo structure to the user.Info interface and calls
// FromUserInfoInterface to return the shoot namespace and name.
-func FromAuthenticationV1UserInfo(userInfo authenticationv1.UserInfo) (namespace string, name string, isAutonomousShoot bool, userType gardenletidentity.UserType) {
+func FromAuthenticationV1UserInfo(userInfo authenticationv1.UserInfo) (namespace string, name string, isSelfHostedShoot bool, userType gardenletidentity.UserType) {
return FromUserInfoInterface(&user.DefaultInfo{
Name: userInfo.Username,
UID: userInfo.UID,
@@ -48,7 +48,7 @@ func FromAuthenticationV1UserInfo(userInfo authenticationv1.UserInfo) (namespace
// FromCertificateSigningRequest converts a *x509.CertificateRequest structure to the user.Info interface and calls
// FromUserInfoInterface to return the shoot namespace and name.
-func FromCertificateSigningRequest(csr *x509.CertificateRequest) (namespace string, name string, isAutonomousShoot bool, userType gardenletidentity.UserType) {
+func FromCertificateSigningRequest(csr *x509.CertificateRequest) (namespace string, name string, isSelfHostedShoot bool, userType gardenletidentity.UserType) {
return FromUserInfoInterface(&user.DefaultInfo{
Name: csr.Subject.CommonName,
Groups: csr.Subject.Organization,
@@ -68,7 +68,7 @@ func convertAuthenticationV1ExtraValueToUserInfoExtra(extra map[string]authentic
return ret
}
-func getIdentityForShootsGroup(u user.Info) (namespace string, name string, isAutonomousShoot bool, userType gardenletidentity.UserType) {
+func getIdentityForShootsGroup(u user.Info) (namespace string, name string, isSelfHostedShoot bool, userType gardenletidentity.UserType) {
userName := u.GetName()
var prefix string
@@ -103,8 +103,8 @@ func userTypeFromPrefix(prefix string) gardenletidentity.UserType {
return ""
}
-func getIdentityForServiceAccountsGroup(_ user.Info) (namespace string, name string, isAutonomousShoot bool, userType gardenletidentity.UserType) {
- // TODO(rfranzke): Implement this function once the concept of how extensions running in autonomous shoots
+func getIdentityForServiceAccountsGroup(_ user.Info) (namespace string, name string, isSelfHostedShoot bool, userType gardenletidentity.UserType) {
+ // TODO(rfranzke): Implement this function once the concept of how extensions running in self-hosted shoots
// authenticate with the garden cluster gets clear.
return "", "", false, gardenletidentity.UserTypeExtension
}
diff --git a/pkg/admissioncontroller/gardenletidentity/shoot/identity_test.go b/pkg/admissioncontroller/gardenletidentity/shoot/identity_test.go
index 80138609e17..be23cfcdf4b 100644
--- a/pkg/admissioncontroller/gardenletidentity/shoot/identity_test.go
+++ b/pkg/admissioncontroller/gardenletidentity/shoot/identity_test.go
@@ -19,12 +19,12 @@ import (
var _ = Describe("identity", func() {
DescribeTable("#FromUserInfoInterface",
- func(u user.Info, expectedShootNamespace, expectedShootName string, expectedIsAutonomousShootValue bool, expectedUserType gardenletidentity.UserType) {
- shootNamespace, shootName, isAutonomousShoot, userType := FromUserInfoInterface(u)
+ func(u user.Info, expectedShootNamespace, expectedShootName string, expectedIsSelfHostedShootValue bool, expectedUserType gardenletidentity.UserType) {
+ shootNamespace, shootName, isSelfHostedShoot, userType := FromUserInfoInterface(u)
Expect(shootNamespace).To(Equal(expectedShootNamespace))
Expect(shootName).To(Equal(expectedShootName))
- Expect(isAutonomousShoot).To(Equal(expectedIsAutonomousShootValue))
+ Expect(isSelfHostedShoot).To(Equal(expectedIsSelfHostedShootValue))
Expect(userType).To(Equal(expectedUserType))
},
@@ -38,12 +38,12 @@ var _ = Describe("identity", func() {
)
DescribeTable("#FromAuthenticationV1UserInfo",
- func(u authenticationv1.UserInfo, expectedShootNamespace, expectedShootName string, expectedIsAutonomousShootValue bool, expectedUserType gardenletidentity.UserType) {
- shootNamespace, shootName, isAutonomousShoot, userType := FromAuthenticationV1UserInfo(u)
+ func(u authenticationv1.UserInfo, expectedShootNamespace, expectedShootName string, expectedIsSelfHostedShootValue bool, expectedUserType gardenletidentity.UserType) {
+ shootNamespace, shootName, isSelfHostedShoot, userType := FromAuthenticationV1UserInfo(u)
Expect(shootNamespace).To(Equal(expectedShootNamespace))
Expect(shootName).To(Equal(expectedShootName))
- Expect(isAutonomousShoot).To(Equal(expectedIsAutonomousShootValue))
+ Expect(isSelfHostedShoot).To(Equal(expectedIsSelfHostedShootValue))
Expect(userType).To(Equal(expectedUserType))
},
@@ -56,12 +56,12 @@ var _ = Describe("identity", func() {
)
DescribeTable("#FromCertificateSigningRequest",
- func(csr *x509.CertificateRequest, expectedShootNamespace, expectedShootName string, expectedIsAutonomousShootValue bool, expectedUserType gardenletidentity.UserType) {
- shootNamespace, shootName, isAutonomousShoot, userType := FromCertificateSigningRequest(csr)
+ func(csr *x509.CertificateRequest, expectedShootNamespace, expectedShootName string, expectedIsSelfHostedShootValue bool, expectedUserType gardenletidentity.UserType) {
+ shootNamespace, shootName, isSelfHostedShoot, userType := FromCertificateSigningRequest(csr)
Expect(shootNamespace).To(Equal(expectedShootNamespace))
Expect(shootName).To(Equal(expectedShootName))
- Expect(isAutonomousShoot).To(Equal(expectedIsAutonomousShootValue))
+ Expect(isSelfHostedShoot).To(Equal(expectedIsSelfHostedShootValue))
Expect(userType).To(Equal(expectedUserType))
},
diff --git a/pkg/admissioncontroller/webhook/admission/shootrestriction/handler.go b/pkg/admissioncontroller/webhook/admission/shootrestriction/handler.go
index 2807ebbd102..a51d28963d9 100644
--- a/pkg/admissioncontroller/webhook/admission/shootrestriction/handler.go
+++ b/pkg/admissioncontroller/webhook/admission/shootrestriction/handler.go
@@ -47,8 +47,8 @@ type Handler struct {
// Handle restricts requests made by gardenlets.
func (h *Handler) Handle(_ context.Context, request admission.Request) admission.Response {
- shootNamespace, shootName, isAutonomousShoot, userType := shootidentity.FromAuthenticationV1UserInfo(request.UserInfo)
- if !isAutonomousShoot {
+ shootNamespace, shootName, isSelfHostedShoot, userType := shootidentity.FromAuthenticationV1UserInfo(request.UserInfo)
+ if !isSelfHostedShoot {
return admissionwebhook.Allowed("")
}
@@ -113,11 +113,11 @@ func (h *Handler) admitGardenlet(gardenletShootInfo types.NamespacedName, reques
return admission.Errored(http.StatusBadRequest, fmt.Errorf("unexpected operation: %q", request.Operation))
}
- if !strings.HasPrefix(request.Name, gardenletutils.ResourcePrefixAutonomousShoot) {
- return admission.Errored(http.StatusBadRequest, fmt.Errorf("the Gardenlet resources for autonomous shoots must be prefixed with %q", gardenletutils.ResourcePrefixAutonomousShoot))
+ if !strings.HasPrefix(request.Name, gardenletutils.ResourcePrefixSelfHostedShoot) {
+ return admission.Errored(http.StatusBadRequest, fmt.Errorf("the Gardenlet resources for self-hosted shoots must be prefixed with %q", gardenletutils.ResourcePrefixSelfHostedShoot))
}
- return h.admit(gardenletShootInfo, types.NamespacedName{Name: strings.TrimPrefix(request.Name, gardenletutils.ResourcePrefixAutonomousShoot), Namespace: request.Namespace})
+ return h.admit(gardenletShootInfo, types.NamespacedName{Name: strings.TrimPrefix(request.Name, gardenletutils.ResourcePrefixSelfHostedShoot), Namespace: request.Namespace})
}
func (h *Handler) admit(gardenletShootInfo, objectShootInfo types.NamespacedName) admission.Response {
diff --git a/pkg/admissioncontroller/webhook/auth/shoot/authorizer.go b/pkg/admissioncontroller/webhook/auth/shoot/authorizer.go
index e9a915b6876..feb9b1eddc7 100644
--- a/pkg/admissioncontroller/webhook/auth/shoot/authorizer.go
+++ b/pkg/admissioncontroller/webhook/auth/shoot/authorizer.go
@@ -31,7 +31,7 @@ import (
authorizerwebhook "github.com/gardener/gardener/pkg/webhook/authorizer"
)
-// NewAuthorizer returns a new authorizer for requests from gardenlets running in autonomous shoots.
+// NewAuthorizer returns a new authorizer for requests from gardenlets running in self-hosted shoots.
func NewAuthorizer(logger logr.Logger, c client.Client, graph graph.Interface, authorizeWithSelectors authorizerwebhook.WithSelectorsChecker) *authorizer {
return &authorizer{
logger: logger,
@@ -69,8 +69,8 @@ var (
)
func (a *authorizer) Authorize(ctx context.Context, attrs auth.Attributes) (auth.Decision, string, error) {
- shootNamespace, shootName, isAutonomousShoot, userType := shootidentity.FromUserInfoInterface(attrs.GetUser())
- if !isAutonomousShoot {
+ shootNamespace, shootName, isSelfHostedShoot, userType := shootidentity.FromUserInfoInterface(attrs.GetUser())
+ if !isSelfHostedShoot {
return auth.DecisionNoOpinion, "", nil
}
@@ -116,7 +116,7 @@ func (a *authorizer) Authorize(ctx context.Context, attrs auth.Attributes) (auth
authwebhook.WithAlwaysAllowedVerbs("create"),
authwebhook.WithAllowedSubresources("status"),
authwebhook.WithAllowedNamespaces(requestAuthorizer.ToNamespace),
- authwebhook.WithFieldSelectors(map[string]string{metav1.ObjectNameField: gardenletutils.ResourcePrefixAutonomousShoot + requestAuthorizer.ToName}),
+ authwebhook.WithFieldSelectors(map[string]string{metav1.ObjectNameField: gardenletutils.ResourcePrefixSelfHostedShoot + requestAuthorizer.ToName}),
)
case secretResource:
diff --git a/pkg/admissioncontroller/webhook/auth/shoot/authorizer_test.go b/pkg/admissioncontroller/webhook/auth/shoot/authorizer_test.go
index 8a68d76efdd..8e912903d01 100644
--- a/pkg/admissioncontroller/webhook/auth/shoot/authorizer_test.go
+++ b/pkg/admissioncontroller/webhook/auth/shoot/authorizer_test.go
@@ -485,7 +485,7 @@ var _ = Describe("Shoot", func() {
attrs.Verb = verb
if withSelector {
- selector, err := fields.ParseSelector("metadata.name=autonomous-shoot-" + shootName)
+ selector, err := fields.ParseSelector("metadata.name=self-hosted-shoot-" + shootName)
Expect(err).NotTo(HaveOccurred())
attrs.FieldSelectorRequirements = selector.Requirements()
}
@@ -569,7 +569,7 @@ var _ = Describe("Shoot", func() {
})
It("should allow if shoot meta matches", func() {
- bootstrapTokenSecret.Data = map[string][]byte{"description": []byte(fmt.Sprintf("Used for connecting the autonomous Shoot %s/%s to the Garden cluster", shootNamespace, shootName))}
+ bootstrapTokenSecret.Data = map[string][]byte{"description": []byte(fmt.Sprintf("Used for connecting the self-hosted Shoot %s/%s to the Garden cluster", shootNamespace, shootName))}
Expect(fakeClient.Create(ctx, bootstrapTokenSecret)).To(Succeed())
decision, reason, err := authorizer.Authorize(ctx, attrs)
@@ -579,7 +579,7 @@ var _ = Describe("Shoot", func() {
})
It("should not have an opinion if shoot meta does not match", func() {
- bootstrapTokenSecret.Data = map[string][]byte{"description": []byte("Used for connecting the autonomous Shoot not-the-namespace/not-the-name to the Garden cluster")}
+ bootstrapTokenSecret.Data = map[string][]byte{"description": []byte("Used for connecting the self-hosted Shoot not-the-namespace/not-the-name to the Garden cluster")}
Expect(fakeClient.Create(ctx, bootstrapTokenSecret)).To(Succeed())
decision, reason, err := authorizer.Authorize(ctx, attrs)
@@ -592,7 +592,7 @@ var _ = Describe("Shoot", func() {
Expect(fakeClient.Create(ctx, bootstrapTokenSecret)).To(Succeed())
decision, reason, err := authorizer.Authorize(ctx, attrs)
- Expect(err).To(MatchError(ContainSubstring(`failed fetching shoot meta from bootstrap token description: bootstrap token description does not start with "Used for connecting the autonomous Shoot "`)))
+ Expect(err).To(MatchError(ContainSubstring(`failed fetching shoot meta from bootstrap token description: bootstrap token description does not start with "Used for connecting the self-hosted Shoot "`)))
Expect(decision).To(Equal(auth.DecisionNoOpinion))
Expect(reason).To(BeEmpty())
})
@@ -943,7 +943,7 @@ var _ = Describe("Shoot", func() {
},
Entry("create", "create"),
- Entry("mark-autonomous", "mark-autonomous"),
+ Entry("mark-self-hosted", "mark-self-hosted"),
)
It("should have no opinion because verb is not allowed", func() {
diff --git a/pkg/admissioncontroller/webhook/auth/shoot/gardenadm.go b/pkg/admissioncontroller/webhook/auth/shoot/gardenadm.go
index 02a97b23010..0dd0f9827fc 100644
--- a/pkg/admissioncontroller/webhook/auth/shoot/gardenadm.go
+++ b/pkg/admissioncontroller/webhook/auth/shoot/gardenadm.go
@@ -32,7 +32,7 @@ func (a *authorizer) authorizeGardenadmRequests(requestLog logr.Logger, shootNam
}
case shootResource:
- if isGardenadmRequestAllowed(attrs, &shootNamespace, "create", "mark-autonomous") {
+ if isGardenadmRequestAllowed(attrs, &shootNamespace, "create", "mark-self-hosted") {
return auth.DecisionAllow, "", nil
}
diff --git a/pkg/apis/core/helper/shoot.go b/pkg/apis/core/helper/shoot.go
index f3535ff67ac..f93e7fdf048 100644
--- a/pkg/apis/core/helper/shoot.go
+++ b/pkg/apis/core/helper/shoot.go
@@ -310,14 +310,14 @@ func IsKubeProxyIPVSMode(kubeProxyConfig *core.KubeProxyConfig) bool {
kubeProxyConfig.Mode != nil && *kubeProxyConfig.Mode == core.ProxyModeIPVS
}
-// IsShootAutonomous returns true if the shoot has a worker pool dedicated for running the control plane components.
-func IsShootAutonomous(workers []core.Worker) bool {
+// IsShootSelfHosted returns true if the shoot has a worker pool dedicated for running the control plane components.
+func IsShootSelfHosted(workers []core.Worker) bool {
return slices.ContainsFunc(workers, func(worker core.Worker) bool {
return worker.ControlPlane != nil
})
}
-// ControlPlaneWorkerPoolForShoot returns the worker pool running the control plane in case the shoot is autonomous.
+// ControlPlaneWorkerPoolForShoot returns the worker pool running the control plane in case the shoot is self-hosted.
func ControlPlaneWorkerPoolForShoot(workers []core.Worker) *core.Worker {
idx := slices.IndexFunc(workers, func(worker core.Worker) bool {
return worker.ControlPlane != nil
diff --git a/pkg/apis/core/helper/shoot_test.go b/pkg/apis/core/helper/shoot_test.go
index bd2515c4dd9..be75fb72446 100644
--- a/pkg/apis/core/helper/shoot_test.go
+++ b/pkg/apis/core/helper/shoot_test.go
@@ -631,12 +631,12 @@ var _ = Describe("Helper", func() {
Entry("with KubeProxy in IPTables mode", &core.KubeProxyConfig{Enabled: ptr.To(true), Mode: ptr.To(core.ProxyModeIPTables)}, false),
)
- Describe("#IsShootAutonomous", func() {
+ Describe("#IsShootSelfHosted", func() {
It("should return true (single worker pool with control plane configuration)", func() {
shoot := &core.Shoot{Spec: core.ShootSpec{Provider: core.Provider{Workers: []core.Worker{
{ControlPlane: &core.WorkerControlPlane{}},
}}}}
- Expect(IsShootAutonomous(shoot.Spec.Provider.Workers)).To(BeTrue())
+ Expect(IsShootSelfHosted(shoot.Spec.Provider.Workers)).To(BeTrue())
})
It("should return true (multiple worker pools, one with control plane configuration)", func() {
@@ -645,12 +645,12 @@ var _ = Describe("Helper", func() {
{ControlPlane: &core.WorkerControlPlane{}},
{},
}}}}
- Expect(IsShootAutonomous(shoot.Spec.Provider.Workers)).To(BeTrue())
+ Expect(IsShootSelfHosted(shoot.Spec.Provider.Workers)).To(BeTrue())
})
It("should return false (no worker pools)", func() {
shoot := &core.Shoot{}
- Expect(IsShootAutonomous(shoot.Spec.Provider.Workers)).To(BeFalse())
+ Expect(IsShootSelfHosted(shoot.Spec.Provider.Workers)).To(BeFalse())
})
It("should return false (worker pools, but none with control plane configuration)", func() {
@@ -659,7 +659,7 @@ var _ = Describe("Helper", func() {
{},
{},
}}}}
- Expect(IsShootAutonomous(shoot.Spec.Provider.Workers)).To(BeFalse())
+ Expect(IsShootSelfHosted(shoot.Spec.Provider.Workers)).To(BeFalse())
})
})
diff --git a/pkg/apis/core/types_shoot.go b/pkg/apis/core/types_shoot.go
index 0d209e07abf..308284982fd 100644
--- a/pkg/apis/core/types_shoot.go
+++ b/pkg/apis/core/types_shoot.go
@@ -1319,7 +1319,7 @@ type Worker struct {
// UpdateStrategy specifies the machine update strategy for the worker pool.
UpdateStrategy *MachineUpdateStrategy
// ControlPlane specifies that the shoot cluster control plane components should be running in this worker pool.
- // This is only relevant for autonomous shoot clusters.
+ // This is only relevant for self-hosted shoot clusters.
ControlPlane *WorkerControlPlane
}
diff --git a/pkg/apis/core/v1beta1/constants/types_constants.go b/pkg/apis/core/v1beta1/constants/types_constants.go
index b6423835267..4cc93d54be7 100644
--- a/pkg/apis/core/v1beta1/constants/types_constants.go
+++ b/pkg/apis/core/v1beta1/constants/types_constants.go
@@ -487,8 +487,8 @@ const (
// LabelKeyAggregateToProjectMember is a constant for a label on ClusterRoles that are aggregated to the project
// member ClusterRole.
LabelKeyAggregateToProjectMember = "rbac.gardener.cloud/aggregate-to-project-member"
- // LabelAutonomousShootCluster is a constant for a label on a Seed indicating that it is an autonomous shoot cluster.
- LabelAutonomousShootCluster = "seed.gardener.cloud/autonomous-shoot-cluster"
+ // LabelSelfHostedShootCluster is a constant for a label on a Seed indicating that it is a self-hosted shoot cluster.
+ LabelSelfHostedShootCluster = "seed.gardener.cloud/self-hosted-shoot-cluster"
// LabelSecretBindingReference is used to identify secrets which are referred by a SecretBinding (not necessarily in the same namespace).
LabelSecretBindingReference = "reference.gardener.cloud/secretbinding"
// LabelCredentialsBindingReference is used to identify credentials which are referred by a CredentialsBinding (not necessarily in the same namespace).
@@ -813,10 +813,10 @@ const (
SeedsGroup = "gardener.cloud:system:seeds"
// SeedUserNamePrefix is the identity username prefix for gardenlets when authenticating to the API server.
SeedUserNamePrefix = "gardener.cloud:system:seed:"
- // ShootsGroup is the identity group for gardenlets running in autonomous shoot clusters when authenticating to the
+ // ShootsGroup is the identity group for gardenlets running in self-hosted shoot clusters when authenticating to the
// API server.
ShootsGroup = "gardener.cloud:system:shoots"
- // ShootUserNamePrefix is the identity username prefix for gardenlets running in autonomous shoot clusters when
+ // ShootUserNamePrefix is the identity username prefix for gardenlets running in self-hosted shoot clusters when
// authenticating to the API server.
ShootUserNamePrefix = "gardener.cloud:system:shoot:"
// GardenadmUserNamePrefix is the identity username prefix for `gardenadm connect` when it bootstraps the
diff --git a/pkg/apis/core/v1beta1/generated.proto b/pkg/apis/core/v1beta1/generated.proto
index 0aa02682d38..404abf251ab 100644
--- a/pkg/apis/core/v1beta1/generated.proto
+++ b/pkg/apis/core/v1beta1/generated.proto
@@ -3796,7 +3796,7 @@ message Worker {
optional string updateStrategy = 23;
// ControlPlane specifies that the shoot cluster control plane components should be running in this worker pool.
- // This is only relevant for autonomous shoot clusters.
+ // This is only relevant for self-hosted shoot clusters.
// +optional
optional WorkerControlPlane controlPlane = 24;
}
diff --git a/pkg/apis/core/v1beta1/helper/shoot.go b/pkg/apis/core/v1beta1/helper/shoot.go
index e5db7a80ee6..86e7f047ba8 100644
--- a/pkg/apis/core/v1beta1/helper/shoot.go
+++ b/pkg/apis/core/v1beta1/helper/shoot.go
@@ -636,20 +636,19 @@ func LastInitiationTimeForWorkerPool(name string, pendingWorkersRollout []garden
return globalLastInitiationTime
}
-// IsShootAutonomous returns true if the shoot has a worker pool dedicated for running the control plane components.
-func IsShootAutonomous(workers []gardencorev1beta1.Worker) bool {
+// IsShootSelfHosted returns true if the shoot has a worker pool dedicated for running the control plane components.
+func IsShootSelfHosted(workers []gardencorev1beta1.Worker) bool {
return slices.ContainsFunc(workers, func(worker gardencorev1beta1.Worker) bool {
return worker.ControlPlane != nil
})
}
// HasManagedInfrastructure returns true if the shoot's infrastructure (network, machines, etc.) is managed by Gardener.
-// I.e., it returns false for high-touch autonomous shoots, where the infrastructure is managed by the user.
func HasManagedInfrastructure(shoot *gardencorev1beta1.Shoot) bool {
return shoot.Spec.CredentialsBindingName != nil || shoot.Spec.SecretBindingName != nil
}
-// ControlPlaneWorkerPoolForShoot returns the worker pool running the control plane in case the shoot is autonomous.
+// ControlPlaneWorkerPoolForShoot returns the worker pool running the control plane in case the shoot is self-hosted.
func ControlPlaneWorkerPoolForShoot(workers []gardencorev1beta1.Worker) *gardencorev1beta1.Worker {
idx := slices.IndexFunc(workers, func(worker gardencorev1beta1.Worker) bool {
return worker.ControlPlane != nil
@@ -661,10 +660,10 @@ func ControlPlaneWorkerPoolForShoot(workers []gardencorev1beta1.Worker) *gardenc
return &workers[idx]
}
-// ControlPlaneNamespaceForShoot returns the control plane namespace for the shoot. If it is an autonomous shoot,
+// ControlPlaneNamespaceForShoot returns the control plane namespace for the shoot. If it is a self-hosted shoot,
// kube-system is returned. Otherwise, it is the technical ID of the shoot.
func ControlPlaneNamespaceForShoot(shoot *gardencorev1beta1.Shoot) string {
- if IsShootAutonomous(shoot.Spec.Provider.Workers) {
+ if IsShootSelfHosted(shoot.Spec.Provider.Workers) {
return metav1.NamespaceSystem
}
return shoot.Status.TechnicalID
@@ -696,9 +695,9 @@ func IsShootIstioTLSTerminationEnabled(shoot *gardencorev1beta1.Shoot) bool {
}
// GetBackupConfigForShoot returns the backup config from the Seed resource in case the shoot is a regular shoot.
-// For autonomous shoots, it is returned from the Shoot resource.
+// For self-hosted shoots, it is returned from the Shoot resource.
func GetBackupConfigForShoot(shoot *gardencorev1beta1.Shoot, seed *gardencorev1beta1.Seed) *gardencorev1beta1.Backup {
- if !IsShootAutonomous(shoot.Spec.Provider.Workers) {
+ if !IsShootSelfHosted(shoot.Spec.Provider.Workers) {
if seed == nil {
return nil
}
diff --git a/pkg/apis/core/v1beta1/helper/shoot_test.go b/pkg/apis/core/v1beta1/helper/shoot_test.go
index f8e62009db0..515fd0eeaeb 100644
--- a/pkg/apis/core/v1beta1/helper/shoot_test.go
+++ b/pkg/apis/core/v1beta1/helper/shoot_test.go
@@ -1428,12 +1428,12 @@ var _ = Describe("Helper", func() {
})
})
- Describe("#IsShootAutonomous", func() {
+ Describe("#IsShootSelfHosted", func() {
It("should return true (single worker pool with control plane configuration)", func() {
shoot := &gardencorev1beta1.Shoot{Spec: gardencorev1beta1.ShootSpec{Provider: gardencorev1beta1.Provider{Workers: []gardencorev1beta1.Worker{
{ControlPlane: &gardencorev1beta1.WorkerControlPlane{}},
}}}}
- Expect(IsShootAutonomous(shoot.Spec.Provider.Workers)).To(BeTrue())
+ Expect(IsShootSelfHosted(shoot.Spec.Provider.Workers)).To(BeTrue())
})
It("should return true (multiple worker pools, one with control plane configuration)", func() {
@@ -1442,12 +1442,12 @@ var _ = Describe("Helper", func() {
{ControlPlane: &gardencorev1beta1.WorkerControlPlane{}},
{},
}}}}
- Expect(IsShootAutonomous(shoot.Spec.Provider.Workers)).To(BeTrue())
+ Expect(IsShootSelfHosted(shoot.Spec.Provider.Workers)).To(BeTrue())
})
It("should return false (no worker pools)", func() {
shoot := &gardencorev1beta1.Shoot{}
- Expect(IsShootAutonomous(shoot.Spec.Provider.Workers)).To(BeFalse())
+ Expect(IsShootSelfHosted(shoot.Spec.Provider.Workers)).To(BeFalse())
})
It("should return false (worker pools, but none with control plane configuration)", func() {
@@ -1456,7 +1456,7 @@ var _ = Describe("Helper", func() {
{},
{},
}}}}
- Expect(IsShootAutonomous(shoot.Spec.Provider.Workers)).To(BeFalse())
+ Expect(IsShootSelfHosted(shoot.Spec.Provider.Workers)).To(BeFalse())
})
})
@@ -1499,7 +1499,7 @@ var _ = Describe("Helper", func() {
})
Describe("#ControlPlaneNamespaceForShoot", func() {
- It("should return kube-system for autonomous shoots", func() {
+ It("should return kube-system for self-hosted shoots", func() {
shoot := &gardencorev1beta1.Shoot{
Spec: gardencorev1beta1.ShootSpec{Provider: gardencorev1beta1.Provider{Workers: []gardencorev1beta1.Worker{{ControlPlane: &gardencorev1beta1.WorkerControlPlane{}}}}},
Status: gardencorev1beta1.ShootStatus{TechnicalID: "shoot--foo--bar"},
@@ -1567,11 +1567,11 @@ var _ = Describe("Helper", func() {
shoot = &gardencorev1beta1.Shoot{}
})
- It("should return the seed backup config because shoot is not autonomous", func() {
+ It("should return the seed backup config because shoot is not self-hosted", func() {
Expect(GetBackupConfigForShoot(shoot, seed)).To(Equal(seedBackup))
})
- It("should return the shoot backup config because shoot is autonomous", func() {
+ It("should return the shoot backup config because shoot is self-hosted", func() {
shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, gardencorev1beta1.Worker{
ControlPlane: &gardencorev1beta1.WorkerControlPlane{Backup: shootBackup},
})
diff --git a/pkg/apis/core/v1beta1/types_shoot.go b/pkg/apis/core/v1beta1/types_shoot.go
index 011c62a1aa4..ae546316215 100644
--- a/pkg/apis/core/v1beta1/types_shoot.go
+++ b/pkg/apis/core/v1beta1/types_shoot.go
@@ -1725,7 +1725,7 @@ type Worker struct {
// +optional
UpdateStrategy *MachineUpdateStrategy `json:"updateStrategy,omitempty" protobuf:"bytes,23,opt,name=updateStrategy,casttype=MachineUpdateStrategy"`
// ControlPlane specifies that the shoot cluster control plane components should be running in this worker pool.
- // This is only relevant for autonomous shoot clusters.
+ // This is only relevant for self-hosted shoot clusters.
// +optional
ControlPlane *WorkerControlPlane `json:"controlPlane,omitempty" protobuf:"bytes,24,opt,name=controlPlane"`
}
diff --git a/pkg/apis/core/validation/shoot.go b/pkg/apis/core/validation/shoot.go
index ac7c42cc739..80be1449b40 100644
--- a/pkg/apis/core/validation/shoot.go
+++ b/pkg/apis/core/validation/shoot.go
@@ -268,7 +268,7 @@ func ValidateShootSpec(meta metav1.ObjectMeta, spec *core.ShootSpec, fldPath *fi
if spec.CredentialsBindingName != nil {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("credentialsBindingName"), workerlessErrorMsg))
}
- } else if !helper.IsShootAutonomous(spec.Provider.Workers) {
+ } else if !helper.IsShootSelfHosted(spec.Provider.Workers) {
if len(ptr.Deref(spec.SecretBindingName, "")) == 0 && len(ptr.Deref(spec.CredentialsBindingName, "")) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("secretBindingName"), "must be set when credentialsBindingName is not"))
} else if len(ptr.Deref(spec.SecretBindingName, "")) != 0 && len(ptr.Deref(spec.CredentialsBindingName, "")) != 0 {
@@ -308,8 +308,8 @@ func ValidateShootSpec(meta metav1.ObjectMeta, spec *core.ShootSpec, fldPath *fi
}
}
- if helper.IsShootAutonomous(spec.Provider.Workers) && spec.SeedName != nil {
- allErrs = append(allErrs, field.Invalid(fldPath.Child("seedName"), *spec.SeedName, "cannot set seedName for autonomous shoots"))
+ if helper.IsShootSelfHosted(spec.Provider.Workers) && spec.SeedName != nil {
+ allErrs = append(allErrs, field.Invalid(fldPath.Child("seedName"), *spec.SeedName, "cannot set seedName for self-hosted shoots"))
}
if spec.SchedulerName != nil {
@@ -479,9 +479,9 @@ func ValidateProviderUpdate(newProvider, oldProvider *core.Provider, fldPath *fi
}
}
- if helper.IsShootAutonomous(oldProvider.Workers) != helper.IsShootAutonomous(newProvider.Workers) {
- allErrs = append(allErrs, field.Forbidden(fldPath.Child("workers"), "cannot switch a Shoot between autonomous and non-autonomous mode"))
- } else if helper.IsShootAutonomous(newProvider.Workers) {
+ if helper.IsShootSelfHosted(oldProvider.Workers) != helper.IsShootSelfHosted(newProvider.Workers) {
+ allErrs = append(allErrs, field.Forbidden(fldPath.Child("workers"), "cannot switch a Shoot between self-hosted and hosted mode"))
+ } else if helper.IsShootSelfHosted(newProvider.Workers) {
oldControlPlaneWorkerPool, newControlPlaneWorkerPool := helper.ControlPlaneWorkerPoolForShoot(oldProvider.Workers), helper.ControlPlaneWorkerPoolForShoot(newProvider.Workers)
if oldControlPlaneWorkerPool.Name != newControlPlaneWorkerPool.Name {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("workers"), "cannot change control plane worker pool"))
@@ -2122,7 +2122,7 @@ func ValidateWorker(worker core.Worker, kubernetes core.Kubernetes, shootNamespa
if worker.ControlPlane != nil {
if worker.Minimum != worker.Maximum || worker.Minimum != 1 {
- allErrs = append(allErrs, field.Invalid(fldPath.Child("minimum"), worker.Minimum, "autonomous shoots only support minimum=maximum=1 for the control plane worker pool (might change in the future)"))
+ allErrs = append(allErrs, field.Invalid(fldPath.Child("minimum"), worker.Minimum, "self-hosted shoots only support minimum=maximum=1 for the control plane worker pool (might change in the future)"))
}
if backup := worker.ControlPlane.Backup; backup != nil {
diff --git a/pkg/apis/core/validation/shoot_test.go b/pkg/apis/core/validation/shoot_test.go
index db3a2b72527..55742d0b816 100644
--- a/pkg/apis/core/validation/shoot_test.go
+++ b/pkg/apis/core/validation/shoot_test.go
@@ -1584,7 +1584,7 @@ var _ = Describe("Shoot Validation Tests", func() {
})
})
- Context("autonomous shoots", func() {
+ Context("self-hosted shoots", func() {
It("should allow 'ControlPlane' field for worker pool", func() {
shoot.Spec.Provider.Workers[0].ControlPlane = &core.WorkerControlPlane{}
@@ -1609,7 +1609,7 @@ var _ = Describe("Shoot Validation Tests", func() {
Expect(ValidateShoot(shoot)).To(ContainElement(PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.seedName"),
- "Detail": ContainSubstring("cannot set seedName for autonomous shoots"),
+ "Detail": ContainSubstring("cannot set seedName for self-hosted shoots"),
}))))
})
@@ -1621,18 +1621,18 @@ var _ = Describe("Shoot Validation Tests", func() {
Expect(ValidateShoot(shoot)).To(ContainElement(PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.provider.workers[0].minimum"),
- "Detail": ContainSubstring("autonomous shoots only support minimum=maximum=1 for the control plane worker pool (might change in the future)"),
+ "Detail": ContainSubstring("self-hosted shoots only support minimum=maximum=1 for the control plane worker pool (might change in the future)"),
}))))
})
- It("should prevent marking a shoot as 'autonomous' after creation", func() {
+ It("should prevent marking a shoot as 'self-hosted' after creation", func() {
newShoot := prepareShootForUpdate(shoot)
shoot.Spec.Provider.Workers[0].ControlPlane = &core.WorkerControlPlane{}
Expect(ValidateShootUpdate(newShoot, shoot)).To(ContainElement(PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeForbidden),
"Field": Equal("spec.provider.workers"),
- "Detail": ContainSubstring("cannot switch a Shoot between autonomous and non-autonomous mode"),
+ "Detail": ContainSubstring("cannot switch a Shoot between self-hosted and hosted mode"),
}))))
})
@@ -1644,7 +1644,7 @@ var _ = Describe("Shoot Validation Tests", func() {
Expect(ValidateShootUpdate(newShoot, shoot)).To(ContainElement(PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeForbidden),
"Field": Equal("spec.provider.workers"),
- "Detail": ContainSubstring("cannot switch a Shoot between autonomous and non-autonomous mode"),
+ "Detail": ContainSubstring("cannot switch a Shoot between self-hosted and hosted mode"),
}))))
})
diff --git a/pkg/apiserver/openapi/openapi_generated.go b/pkg/apiserver/openapi/openapi_generated.go
index a8e2442480a..05d2c502b8e 100644
--- a/pkg/apiserver/openapi/openapi_generated.go
+++ b/pkg/apiserver/openapi/openapi_generated.go
@@ -10636,7 +10636,7 @@ func schema_pkg_apis_core_v1beta1_Worker(ref common.ReferenceCallback) common.Op
},
"controlPlane": {
SchemaProps: spec.SchemaProps{
- Description: "ControlPlane specifies that the shoot cluster control plane components should be running in this worker pool. This is only relevant for autonomous shoot clusters.",
+ Description: "ControlPlane specifies that the shoot cluster control plane components should be running in this worker pool. This is only relevant for self-hosted shoot clusters.",
Ref: ref("github.com/gardener/gardener/pkg/apis/core/v1beta1.WorkerControlPlane"),
},
},
diff --git a/pkg/component/extensions/operatingsystemconfig/operatingsystemconfig.go b/pkg/component/extensions/operatingsystemconfig/operatingsystemconfig.go
index e26577fc224..c598c5573c1 100644
--- a/pkg/component/extensions/operatingsystemconfig/operatingsystemconfig.go
+++ b/pkg/component/extensions/operatingsystemconfig/operatingsystemconfig.go
@@ -1075,7 +1075,7 @@ func KeyV2(
)
if worker.Machine.Image != nil {
- // worker.Machine.Image.Version is unset for autonomous shoots with unmanaged infrastructure
+ // worker.Machine.Image.Version is unset for self-hosted shoots with unmanaged infrastructure
data = append(data, worker.Machine.Image.Name+ptr.Deref(worker.Machine.Image.Version, ""))
}
diff --git a/pkg/component/garden/system/virtual/virtual.go b/pkg/component/garden/system/virtual/virtual.go
index ebceb164345..24c0af956a2 100644
--- a/pkg/component/garden/system/virtual/virtual.go
+++ b/pkg/component/garden/system/virtual/virtual.go
@@ -148,7 +148,7 @@ func (g *gardenSystem) computeResourcesData() (map[string][]byte, error) {
{
APIGroups: []string{gardencorev1beta1.GroupName},
Resources: []string{"*"},
- Verbs: []string{"create", "delete", "deletecollection", "get", "list", "watch", "patch", "update", "manage-members", "modify-spec-tolerations-whitelist", "modify-spec-kubernetes", "modify-spec-machineimages", "modify-spec-providerconfig", "mark-autonomous"},
+ Verbs: []string{"create", "delete", "deletecollection", "get", "list", "watch", "patch", "update", "manage-members", "modify-spec-tolerations-whitelist", "modify-spec-kubernetes", "modify-spec-machineimages", "modify-spec-providerconfig", "mark-self-hosted"},
},
{
APIGroups: []string{
diff --git a/pkg/component/garden/system/virtual/virtual_test.go b/pkg/component/garden/system/virtual/virtual_test.go
index 53b9773b840..dce52016a4e 100644
--- a/pkg/component/garden/system/virtual/virtual_test.go
+++ b/pkg/component/garden/system/virtual/virtual_test.go
@@ -170,7 +170,7 @@ var _ = Describe("Virtual", func() {
{
APIGroups: []string{"core.gardener.cloud"},
Resources: []string{"*"},
- Verbs: []string{"create", "delete", "deletecollection", "get", "list", "watch", "patch", "update", "manage-members", "modify-spec-tolerations-whitelist", "modify-spec-kubernetes", "modify-spec-machineimages", "modify-spec-providerconfig", "mark-autonomous"},
+ Verbs: []string{"create", "delete", "deletecollection", "get", "list", "watch", "patch", "update", "manage-members", "modify-spec-tolerations-whitelist", "modify-spec-kubernetes", "modify-spec-machineimages", "modify-spec-providerconfig", "mark-self-hosted"},
},
{
APIGroups: []string{
diff --git a/pkg/component/gardener/resourcemanager/resource_manager.go b/pkg/component/gardener/resourcemanager/resource_manager.go
index 42a585e4b20..b288b84b835 100644
--- a/pkg/component/gardener/resourcemanager/resource_manager.go
+++ b/pkg/component/gardener/resourcemanager/resource_manager.go
@@ -360,7 +360,7 @@ const (
// the virtual garden cluster, or GRM in a seed cluster, being responsible for a shoot cluster).
ForTarget ResponsibilityMode = "target"
// ForSourceAndTarget is a deployment mode for a gardener-resource-manager deployed in a source cluster,
- // taking over responsibilities for both the source and a target cluster (e.g., GRM in an autonomous shoot cluster
+ // taking over responsibilities for both the source and a target cluster (e.g., GRM in a self-hosted shoot cluster
// where the control plane is running in the cluster itself).
ForSourceAndTarget ResponsibilityMode = "both"
)
diff --git a/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager.go b/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager.go
index 002cfaa6268..eb694fc445e 100644
--- a/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager.go
+++ b/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager.go
@@ -89,15 +89,15 @@ type Values struct {
Image string
// Replicas is the number of replicas for the deployment.
Replicas int32
- // AutonomousShoot is true if the machine-controller-manager is deployed for an autonomous shoot cluster.
- AutonomousShoot bool
+ // SelfHostedShoot is true if the machine-controller-manager is deployed for a self-hosted shoot cluster.
+ SelfHostedShoot bool
}
func (m *machineControllerManager) Deploy(ctx context.Context) error {
var (
// In `gardenadm bootstrap`, machine-controller-manager runs without a target cluster. We don't need the shoot
// resources (e.g., RBAC) in this case.
- hasTargetCluster = !m.values.AutonomousShoot || m.namespace == metav1.NamespaceSystem
+ hasTargetCluster = !m.values.SelfHostedShoot || m.namespace == metav1.NamespaceSystem
shootAccessSecret = m.newShootAccessSecret()
serviceAccount = m.emptyServiceAccount()
@@ -207,7 +207,7 @@ func (m *machineControllerManager) Deploy(ctx context.Context) error {
return err
}
- if !m.values.AutonomousShoot {
+ if !m.values.SelfHostedShoot {
if err := shootAccessSecret.Reconcile(ctx, m.client); err != nil {
return err
}
@@ -247,7 +247,7 @@ func (m *machineControllerManager) Deploy(ctx context.Context) error {
fmt.Sprintf("--port=%d", portMetrics),
"--safety-up=2",
"--safety-down=1",
- "--target-kubeconfig=" + targetKubeconfig(m.values.AutonomousShoot, m.namespace),
+ "--target-kubeconfig=" + targetKubeconfig(m.values.SelfHostedShoot, m.namespace),
"--concurrent-syncs=30",
"--kube-api-qps=150",
"--kube-api-burst=200",
@@ -289,7 +289,7 @@ func (m *machineControllerManager) Deploy(ctx context.Context) error {
},
}
- if !m.values.AutonomousShoot {
+ if !m.values.SelfHostedShoot {
genericTokenKubeconfigSecret, found := m.secretsManager.Get(v1beta1constants.SecretNameGenericTokenKubeconfig)
if !found {
return fmt.Errorf("secret %q not found", v1beta1constants.SecretNameGenericTokenKubeconfig)
@@ -484,8 +484,8 @@ func (m *machineControllerManager) Deploy(ctx context.Context) error {
}
// targetKubeconfig returns the path to the target kubeconfig file depending on the shoot configuration.
-func targetKubeconfig(autonomousShoot bool, controlPlaneNamespace string) string {
- if !autonomousShoot {
+func targetKubeconfig(selfHostedShoot bool, controlPlaneNamespace string) string {
+ if !selfHostedShoot {
return gardenerutils.PathGenericKubeconfig
}
@@ -494,7 +494,7 @@ func targetKubeconfig(autonomousShoot bool, controlPlaneNamespace string) string
return ""
}
- // There is no control plane for the autonomous shoot cluster yet, i.e., we're creating machines for the control plane
+ // There is no control plane for the self-hosted shoot cluster yet, i.e., we're creating machines for the control plane
// nodes with `gardenadm bootstrap`. machine-controller-manager should not interact with a target cluster.
return "none"
}
diff --git a/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager_test.go b/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager_test.go
index 54eb7789f81..c7e160a674b 100644
--- a/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager_test.go
+++ b/pkg/component/nodemanagement/machinecontrollermanager/machine_controller_manager_test.go
@@ -597,7 +597,7 @@ subjects:
Expect(actualServiceMonitor).To(DeepEqual(serviceMonitor))
actualManagedResource := &resourcesv1alpha1.ManagedResource{}
- if values.AutonomousShoot && namespace != "kube-system" {
+ if values.SelfHostedShoot && namespace != "kube-system" {
Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(managedResource), actualManagedResource)).To(BeNotFoundError())
} else {
Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(managedResource), actualManagedResource)).To(Succeed())
@@ -624,7 +624,7 @@ subjects:
}
}
- When("the shoot is not autonomous", func() {
+ When("the shoot is not self-hosted", func() {
JustBeforeEach(func() {
Expect(gardenerutils.InjectGenericKubeconfig(deployment, "generic-token-kubeconfig", shootAccessSecret.Name)).To(Succeed())
})
@@ -639,9 +639,9 @@ subjects:
})
})
- When("the shoot is autonomous", func() {
+ When("the shoot is self-hosted", func() {
BeforeEach(func() {
- values.AutonomousShoot = true
+ values.SelfHostedShoot = true
})
JustBeforeEach(func() {
diff --git a/pkg/component/nodemanagement/machinecontrollermanager/provider.go b/pkg/component/nodemanagement/machinecontrollermanager/provider.go
index d9648019580..0d6390f3494 100644
--- a/pkg/component/nodemanagement/machinecontrollermanager/provider.go
+++ b/pkg/component/nodemanagement/machinecontrollermanager/provider.go
@@ -28,7 +28,7 @@ const (
// implementations when the standard sidecar container is required.
// The shoot object can be read from the `Cluster` object, e.g., using the GardenContext.GetCluster method in webhooks.
func ProviderSidecarContainer(shoot *gardencorev1beta1.Shoot, controlPlaneNamespace, providerName, image string) corev1.Container {
- autonomousShoot := v1beta1helper.IsShootAutonomous(shoot.Spec.Provider.Workers)
+ selfHostedShoot := v1beta1helper.IsShootSelfHosted(shoot.Spec.Provider.Workers)
c := corev1.Container{
Name: providerSidecarContainerName(providerName),
@@ -46,7 +46,7 @@ func ProviderSidecarContainer(shoot *gardencorev1beta1.Shoot, controlPlaneNamesp
"--machine-safety-orphan-vms-period=30m",
"--namespace=" + controlPlaneNamespace,
"--port=" + strconv.Itoa(portProviderMetrics),
- "--target-kubeconfig=" + targetKubeconfig(autonomousShoot, controlPlaneNamespace),
+ "--target-kubeconfig=" + targetKubeconfig(selfHostedShoot, controlPlaneNamespace),
"--v=3",
},
LivenessProbe: &corev1.Probe{
@@ -79,7 +79,7 @@ func ProviderSidecarContainer(shoot *gardencorev1beta1.Shoot, controlPlaneNamesp
},
}
- if !autonomousShoot {
+ if !selfHostedShoot {
c.VolumeMounts = append(c.VolumeMounts, corev1.VolumeMount{
Name: "kubeconfig",
MountPath: gardenerutils.VolumeMountPathGenericKubeconfig,
diff --git a/pkg/component/nodemanagement/machinecontrollermanager/provider_test.go b/pkg/component/nodemanagement/machinecontrollermanager/provider_test.go
index adde1d032b9..ab279e12b1d 100644
--- a/pkg/component/nodemanagement/machinecontrollermanager/provider_test.go
+++ b/pkg/component/nodemanagement/machinecontrollermanager/provider_test.go
@@ -89,7 +89,7 @@ var _ = Describe("Provider", func() {
}
})
- When("the shoot is not autonomous", func() {
+ When("the shoot is not self-hosted", func() {
JustBeforeEach(func() {
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
Name: "kubeconfig",
@@ -103,7 +103,7 @@ var _ = Describe("Provider", func() {
})
})
- When("the shoot is autonomous", func() {
+ When("the shoot is self-hosted", func() {
BeforeEach(func() {
shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, gardencorev1beta1.Worker{
ControlPlane: &gardencorev1beta1.WorkerControlPlane{},
diff --git a/pkg/component/shared/resourcemanager.go b/pkg/component/shared/resourcemanager.go
index c01a0b57f84..bb7f7aa523b 100644
--- a/pkg/component/shared/resourcemanager.go
+++ b/pkg/component/shared/resourcemanager.go
@@ -133,7 +133,7 @@ func combinedGardenerResourceManagerDefaultValues() resourcemanager.Values {
}
// NewCombinedGardenerResourceManager instantiates a new `gardener-resource-manager` component configured to reconcile
-// objects in an autonomous shoot cluster.
+// objects in a self-hosted shoot cluster.
func NewCombinedGardenerResourceManager(c client.Client,
namespaceName string,
secretsManager secretsmanager.Interface,
diff --git a/pkg/controller/gardenletdeployer/actuator.go b/pkg/controller/gardenletdeployer/actuator.go
index 4a701f5b6ef..52dc4c8d5b2 100644
--- a/pkg/controller/gardenletdeployer/actuator.go
+++ b/pkg/controller/gardenletdeployer/actuator.go
@@ -685,7 +685,7 @@ func PrepareGardenletChartValues(
}
}
- // Ensure seed name is set if we are not deploying gardenlet into an autonomous shoot cluster
+ // Ensure seed name is set if we are not deploying gardenlet into a self-hosted shoot cluster
if gardenletConfig.SeedConfig != nil {
gardenletConfig.SeedConfig.Name = obj.GetName()
}
@@ -725,7 +725,7 @@ func PrepareGardenletChartValues(
return values, nil
}
- // enable self-upgrades for autonomous shoots
+ // enable self-upgrades for self-hosted shoots
gardenletChartImage, err := imagevector.Charts().FindImage(imagevector.ChartImageNameGardenlet)
if err != nil {
return nil, fmt.Errorf("failed fetching gardenlet chart image: %w", err)
@@ -733,7 +733,7 @@ func PrepareGardenletChartValues(
gardenletChartImage.WithOptionalTag(version.Get().GitVersion)
return utils.SetToValuesMap(values, map[string]any{
- "name": gardenletutils.ResourcePrefixAutonomousShoot + shoot.Name,
+ "name": gardenletutils.ResourcePrefixSelfHostedShoot + shoot.Name,
"namespace": shoot.Namespace,
"deployment": map[string]any{"helm": map[string]any{"ociRepository": map[string]any{"ref": gardenletChartImage.String()}}},
}, "selfUpgrade")
diff --git a/pkg/controller/gardenletdeployer/actuator_test.go b/pkg/controller/gardenletdeployer/actuator_test.go
index 57205b11c9d..2a5848a8b93 100644
--- a/pkg/controller/gardenletdeployer/actuator_test.go
+++ b/pkg/controller/gardenletdeployer/actuator_test.go
@@ -438,7 +438,7 @@ var _ = Describe("Interface", func() {
)
}
- expectGetGardenletChartValues = func(withBootstrap, seedIsGarden, autonomousShoot bool) {
+ expectGetGardenletChartValues = func(withBootstrap, seedIsGarden, selfHostedShoot bool) {
gardenletChartValues = map[string]any{"foo": "bar"}
vh.EXPECT().GetGardenletChartValues(gomock.AssignableToTypeOf(&seedmanagementv1alpha1.GardenletDeployment{}), gomock.AssignableToTypeOf(&gardenletconfigv1alpha1.GardenletConfiguration{}), gomock.AssignableToTypeOf("")).DoAndReturn(
@@ -465,7 +465,7 @@ var _ = Describe("Interface", func() {
Expect(deployment.PodLabels).To(BeEmpty())
}
- if !autonomousShoot {
+ if !selfHostedShoot {
Expect(gc.SeedConfig.SeedTemplate).To(Equal(gardencorev1beta1.SeedTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@@ -737,7 +737,7 @@ var _ = Describe("Interface", func() {
})
})
- Context("autonomous shoot", func() {
+ Context("self-hosted shoot", func() {
var (
deployment *seedmanagementv1alpha1.GardenletDeployment
config *gardenletconfigv1alpha1.GardenletConfiguration
diff --git a/pkg/controllermanager/controller/certificatesigningrequest/reconciler.go b/pkg/controllermanager/controller/certificatesigningrequest/reconciler.go
index 686dc0ddead..7c23cf40753 100644
--- a/pkg/controllermanager/controller/certificatesigningrequest/reconciler.go
+++ b/pkg/controllermanager/controller/certificatesigningrequest/reconciler.go
@@ -116,7 +116,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
}
default:
- log.Info("Ignoring CSR, as it does not match the requirements for a seed client or an autonomous shoot client", "reasonSeedCheck", reasonSeed, "reasonShootCheck", reasonShoot, "reasonGardenadmCheck", reasonGardenadm)
+ log.Info("Ignoring CSR, as it does not match the requirements for a seed client or a self-hosted shoot client", "reasonSeedCheck", reasonSeed, "reasonShootCheck", reasonShoot, "reasonGardenadmCheck", reasonGardenadm)
return reconcile.Result{}, nil
}
diff --git a/pkg/controllermanager/controller/certificatesigningrequest/reconciler_test.go b/pkg/controllermanager/controller/certificatesigningrequest/reconciler_test.go
index 21140317e9c..f21dc16ec9a 100644
--- a/pkg/controllermanager/controller/certificatesigningrequest/reconciler_test.go
+++ b/pkg/controllermanager/controller/certificatesigningrequest/reconciler_test.go
@@ -316,7 +316,7 @@ var _ = Describe("Reconciler", func() {
})
When("bootstrap token secret has invalid description", func() {
- It("should lead to denial of the CSR when description does not have autonomous shoot prefix", func() {
+ It("should lead to denial of the CSR when description does not have self-hosted shoot prefix", func() {
bootstrapTokenSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: bootstrapTokenName,
@@ -362,7 +362,7 @@ var _ = Describe("Reconciler", func() {
Namespace: metav1.NamespaceSystem,
},
Data: map[string][]byte{
- bootstraptokenapi.BootstrapTokenDescriptionKey: []byte(bootstraptoken.AutonomousShootBootstrapTokenSecretDescriptionPrefix + "invalid-format"),
+ bootstraptokenapi.BootstrapTokenDescriptionKey: []byte(bootstraptoken.SelfHostedShootBootstrapTokenSecretDescriptionPrefix + "invalid-format"),
},
}
@@ -414,7 +414,7 @@ var _ = Describe("Reconciler", func() {
Namespace: metav1.NamespaceSystem,
},
Data: map[string][]byte{
- bootstraptokenapi.BootstrapTokenDescriptionKey: []byte(bootstraptoken.AutonomousShootBootstrapTokenSecretDescriptionPrefix + shootNamespace + "/" + shootName),
+ bootstraptokenapi.BootstrapTokenDescriptionKey: []byte(bootstraptoken.SelfHostedShootBootstrapTokenSecretDescriptionPrefix + shootNamespace + "/" + shootName),
},
}
@@ -453,7 +453,7 @@ var _ = Describe("Reconciler", func() {
Namespace: metav1.NamespaceSystem,
},
Data: map[string][]byte{
- bootstraptokenapi.BootstrapTokenDescriptionKey: []byte(bootstraptoken.AutonomousShootBootstrapTokenSecretDescriptionPrefix + shootNamespace + "/" + shootName),
+ bootstraptokenapi.BootstrapTokenDescriptionKey: []byte(bootstraptoken.SelfHostedShootBootstrapTokenSecretDescriptionPrefix + shootNamespace + "/" + shootName),
},
}
@@ -494,7 +494,7 @@ var _ = Describe("Reconciler", func() {
Namespace: metav1.NamespaceSystem,
},
Data: map[string][]byte{
- bootstraptokenapi.BootstrapTokenDescriptionKey: []byte(bootstraptoken.AutonomousShootBootstrapTokenSecretDescriptionPrefix + shootNamespace + "/" + shootName),
+ bootstraptokenapi.BootstrapTokenDescriptionKey: []byte(bootstraptoken.SelfHostedShootBootstrapTokenSecretDescriptionPrefix + shootNamespace + "/" + shootName),
},
}
diff --git a/pkg/gardenadm/botanist/bastion.go b/pkg/gardenadm/botanist/bastion.go
index 6742a6e7ce6..83ca2ffbfb4 100644
--- a/pkg/gardenadm/botanist/bastion.go
+++ b/pkg/gardenadm/botanist/bastion.go
@@ -9,7 +9,7 @@ import (
)
// DefaultBastion creates the Bastion component for accessing the control plane machines in `gardenadm bootstrap`.
-func (b *AutonomousBotanist) DefaultBastion() *bastion.Bastion {
+func (b *GardenadmBotanist) DefaultBastion() *bastion.Bastion {
return bastion.New(b.Logger, b.SeedClientSet.Client(), b.SecretsManager, &bastion.Values{
Name: "gardenadm-bootstrap",
Namespace: b.Shoot.ControlPlaneNamespace,
diff --git a/pkg/gardenadm/botanist/botanist.go b/pkg/gardenadm/botanist/botanist.go
index e0b221d4302..94a896ee69b 100644
--- a/pkg/gardenadm/botanist/botanist.go
+++ b/pkg/gardenadm/botanist/botanist.go
@@ -48,8 +48,8 @@ import (
// even when running `gardenadm bootstrap` on Windows.
const GardenadmBaseDir = "/var/lib/gardenadm"
-// AutonomousBotanist is a struct which has methods that perform operations for an autonomous shoot cluster.
-type AutonomousBotanist struct {
+// GardenadmBotanist is a struct which has methods that perform operations for a self-hosted shoot cluster.
+type GardenadmBotanist struct {
*botanistpkg.Botanist
HostName string
@@ -89,15 +89,15 @@ var (
NewFs = afero.NewOsFs
)
-// NewAutonomousBotanistFromManifests reads the manifests from dir and initializes a new AutonomousBotanist with them.
-func NewAutonomousBotanistFromManifests(
+// NewGardenadmBotanistFromManifests reads the manifests from dir and initializes a new GardenadmBotanist with them.
+func NewGardenadmBotanistFromManifests(
ctx context.Context,
log logr.Logger,
clientSet kubernetes.Interface,
dir string,
runsControlPlane bool,
) (
- *AutonomousBotanist,
+ *GardenadmBotanist,
error,
) {
resources, err := gardenadm.ReadManifests(log, DirFS(dir))
@@ -110,7 +110,7 @@ func NewAutonomousBotanistFromManifests(
return nil, fmt.Errorf("failed computing extensions: %w", err)
}
- b, err := NewAutonomousBotanist(ctx, log, clientSet, resources, extensions, runsControlPlane)
+ b, err := NewGardenadmBotanist(ctx, log, clientSet, resources, extensions, runsControlPlane)
if err != nil {
return nil, fmt.Errorf("failed constructing botanist: %w", err)
}
@@ -118,8 +118,8 @@ func NewAutonomousBotanistFromManifests(
return b, nil
}
-// NewAutonomousBotanist creates a new botanist.AutonomousBotanist instance for the gardenadm command execution.
-func NewAutonomousBotanist(
+// NewGardenadmBotanist creates a new botanist.GardenadmBotanist instance for the gardenadm command execution.
+func NewGardenadmBotanist(
ctx context.Context,
log logr.Logger,
clientSet kubernetes.Interface,
@@ -127,15 +127,15 @@ func NewAutonomousBotanist(
extensions []Extension,
runsControlPlane bool,
) (
- *AutonomousBotanist,
+ *GardenadmBotanist,
error,
) {
- autonomousBotanist, err := NewAutonomousBotanistWithoutResources(log)
+ gardenadmBotanist, err := NewGardenadmBotanistWithoutResources(log)
if err != nil {
- return nil, fmt.Errorf("failed creating autonomous botanist: %w", err)
+ return nil, fmt.Errorf("failed creating gardenadm botanist: %w", err)
}
- if err := initializeShootResource(resources, autonomousBotanist.FS, runsControlPlane); err != nil {
+ if err := initializeShootResource(resources, gardenadmBotanist.FS, runsControlPlane); err != nil {
return nil, fmt.Errorf("failed initializing shoot resource: %w", err)
}
@@ -146,36 +146,36 @@ func NewAutonomousBotanist(
return nil, fmt.Errorf("failed initializing resources in fake garden client: %w", err)
}
- autonomousBotanist.Botanist, err = newBotanist(ctx, log, clientSet, gardenClient, resources, runsControlPlane)
+ gardenadmBotanist.Botanist, err = newBotanist(ctx, log, clientSet, gardenClient, resources, runsControlPlane)
if err != nil {
return nil, fmt.Errorf("failed creating botanist: %w", err)
}
- if !autonomousBotanist.Shoot.RunsControlPlane() {
- autonomousBotanist.Bastion = autonomousBotanist.DefaultBastion()
+ if !gardenadmBotanist.Shoot.RunsControlPlane() {
+ gardenadmBotanist.Bastion = gardenadmBotanist.DefaultBastion()
// For `gardenadm bootstrap`, we don't initialize the control plane machines with a "full OSC".
// Instead, we provide a small alternative OSC, that only fetches the `gardenadm` binary from the registry.
- autonomousBotanist.Shoot.Components.Extensions.OperatingSystemConfig, err = autonomousBotanist.ControlPlaneBootstrapOperatingSystemConfig()
+ gardenadmBotanist.Shoot.Components.Extensions.OperatingSystemConfig, err = gardenadmBotanist.ControlPlaneBootstrapOperatingSystemConfig()
if err != nil {
return nil, err
}
}
- autonomousBotanist.Resources = resources
- autonomousBotanist.Extensions = extensions
+ gardenadmBotanist.Resources = resources
+ gardenadmBotanist.Extensions = extensions
- return autonomousBotanist, nil
+ return gardenadmBotanist, nil
}
-// NewAutonomousBotanistWithoutResources creates a new AutonomousBotanist without instantiating a Botanist struct.
-func NewAutonomousBotanistWithoutResources(log logr.Logger) (*AutonomousBotanist, error) {
+// NewGardenadmBotanistWithoutResources creates a new GardenadmBotanist without instantiating a Botanist struct.
+func NewGardenadmBotanistWithoutResources(log logr.Logger) (*GardenadmBotanist, error) {
hostName, err := nodeagent.GetHostName()
if err != nil {
return nil, fmt.Errorf("failed fetching hostname: %w", err)
}
- return &AutonomousBotanist{
+ return &GardenadmBotanist{
Botanist: &botanistpkg.Botanist{Operation: newOperation(log, newFakeGardenClient(), newFakeSeedClientSet(""))},
HostName: hostName,
@@ -223,9 +223,9 @@ func newBotanist(
keysAndValues := []any{"cloudProfile", resources.CloudProfile, "project", resources.Project, "shoot", resources.Shoot}
if clientSet == nil {
clientSet = newFakeSeedClientSet(seedObj.KubernetesVersion.String())
- log.Info("Initializing autonomous botanist with fake client set", keysAndValues...) //nolint:logcheck
+ log.Info("Initializing gardenadm botanist with fake client set", keysAndValues...) //nolint:logcheck
} else {
- log.Info("Initializing autonomous botanist with control plane client set", keysAndValues...) //nolint:logcheck
+ log.Info("Initializing gardenadm botanist with control plane client set", keysAndValues...) //nolint:logcheck
}
o := newOperation(log, gardenClient, clientSet)
@@ -330,11 +330,11 @@ func newShootObject(
return nil, fmt.Errorf("failed computing shoot networks: %w", err)
}
- // In autonomous shoot clusters, kube-system is used as the control plane namespace.
- // However, when bootstrapping an autonomous shoot cluster with `gardenadm bootstrap` using a temporary local cluster,
+ // In self-hosted shoot clusters, kube-system is used as the control plane namespace.
+ // However, when bootstrapping a self-hosted shoot cluster with `gardenadm bootstrap` using a temporary local cluster,
// we want to avoid conflicts with kube-system components of the bootstrap cluster by placing all shoot-related
// components in another namespace. In this case, we use the technical ID as the control plane namespace, as usual.
- // TODO(timebertt): double-check if this causes problems when importing the state into the autonomous shoot cluster
+ // TODO(timebertt): double-check if this causes problems when importing the state into the self-hosted shoot cluster
if !runsControlPlane {
obj.ControlPlaneNamespace = resources.Shoot.Status.TechnicalID
}
@@ -388,7 +388,7 @@ func initializeShootResource(resources gardenadm.Resources, fs afero.Afero, runs
if resources.ShootState == nil {
return fmt.Errorf("shoot has managed infrastructure, but ShootState is missing " +
"(the ShootState is usually exported by `gardenadm bootstrap` and read by `gardenadm init`): " +
- "you should either use `gardenadm bootstrap` to create the autonomous shoot cluster with managed infrastructure or " +
+ "you should either use `gardenadm bootstrap` to create the self-hosted shoot cluster with managed infrastructure or " +
"remove the `Shoot.spec.{secret,credentials}BindingName` field to mark the shoot as having unmanaged infrastructure")
}
@@ -412,11 +412,11 @@ func initializeSeedResource(resources gardenadm.Resources, runsControlPlane bool
seed.Status = gardencorev1beta1.SeedStatus{ClusterIdentity: ptr.To(resources.Shoot.Name)}
if runsControlPlane {
- // When running the control plane (`gardenadm init`), mark the seed as an autonomous shoot cluster.
+ // When running the control plane (`gardenadm init`), mark the seed as a self-hosted shoot cluster.
// Otherwise (`gardenadm bootstrap`), the bootstrap cluster should behave like a standard seed cluster.
- // If the seed is marked as an autonomous shoot cluster, extensions are configured differently, e.g., they merge the
+ // If the seed is marked as a self-hosted shoot cluster, extensions are configured differently, e.g., they merge the
// shoot webhooks into the seed webhooks.
- metav1.SetMetaDataLabel(&seed.ObjectMeta, v1beta1constants.LabelAutonomousShootCluster, "true")
+ metav1.SetMetaDataLabel(&seed.ObjectMeta, v1beta1constants.LabelSelfHostedShootCluster, "true")
}
kubernetes.GardenScheme.Default(seed)
diff --git a/pkg/gardenadm/botanist/botanist_test.go b/pkg/gardenadm/botanist/botanist_test.go
index edff501def8..cfc370d3681 100644
--- a/pkg/gardenadm/botanist/botanist_test.go
+++ b/pkg/gardenadm/botanist/botanist_test.go
@@ -24,8 +24,8 @@ import (
"github.com/gardener/gardener/pkg/utils/test"
)
-var _ = Describe("AutonomousBotanist", func() {
- Describe("#NewAutonomousBotanistFromManifests", func() {
+var _ = Describe("GardenadmBotanist", func() {
+ Describe("#NewGardenadmBotanistFromManifests", func() {
const configDir = "manifests"
var (
@@ -50,13 +50,13 @@ var _ = Describe("AutonomousBotanist", func() {
})
It("should fail if the directory does not exist", func() {
- Expect(NewAutonomousBotanistFromManifests(ctx, log, nil, "does/not/exist", false)).Error().To(MatchError(fs.ErrNotExist))
+ Expect(NewGardenadmBotanistFromManifests(ctx, log, nil, "does/not/exist", false)).Error().To(MatchError(fs.ErrNotExist))
})
- When("running the control plane (acting on the autonomous shoot cluster)", func() {
- Context("with unmanaged infrastructure (high-touch scenario)", func() {
- It("should create a new Autonomous Botanist", func() {
- b, err := NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, true)
+ When("running the control plane (acting on the self-hosted shoot cluster)", func() {
+ Context("with unmanaged infrastructure", func() {
+ It("should create a new Self-Hosted Botanist", func() {
+ b, err := NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, true)
Expect(err).NotTo(HaveOccurred())
Expect(b.Shoot.CloudProfile.Name).To(Equal("stackit"))
@@ -66,11 +66,11 @@ var _ = Describe("AutonomousBotanist", func() {
HaveField("ControllerRegistration.Name", "provider-stackit"),
HaveField("ControllerRegistration.Name", "networking-cilium"),
))
- Expect(b.Seed.GetInfo()).To(HaveField("ObjectMeta.Labels", HaveKeyWithValue("seed.gardener.cloud/autonomous-shoot-cluster", "true")))
+ Expect(b.Seed.GetInfo()).To(HaveField("ObjectMeta.Labels", HaveKeyWithValue("seed.gardener.cloud/self-hosted-shoot-cluster", "true")))
})
})
- Context("with managed infrastructure (medium-touch scenario)", func() {
+ Context("with managed infrastructure", func() {
BeforeEach(func() {
shootFile := fsys[configDir+"/shoot.yaml"]
shootFile.Data = append(shootFile.Data, []byte("\n credentialsBindingName: provider-account\n")...)
@@ -84,11 +84,11 @@ metadata:
It("should fail if the ShootState is missing", func() {
delete(fsys, configDir+"/shootstate.yaml")
- Expect(NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, true)).Error().To(MatchError(ContainSubstring("ShootState is missing")))
+ Expect(NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, true)).Error().To(MatchError(ContainSubstring("ShootState is missing")))
})
It("should set the LastOperation to Restore and fetch the ShootState", func() {
- b, err := NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, true)
+ b, err := NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, true)
Expect(err).NotTo(HaveOccurred())
Expect(b.Shoot.GetInfo().Status.LastOperation.Type).To(Equal(gardencorev1beta1.LastOperationTypeRestore))
@@ -98,7 +98,7 @@ metadata:
})
It("should use kube-system as the control plane namespace", func() {
- b, err := NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, true)
+ b, err := NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, true)
Expect(err).NotTo(HaveOccurred())
Expect(b.Shoot.ControlPlaneNamespace).To(Equal("kube-system"))
})
@@ -108,7 +108,7 @@ metadata:
DeferCleanup(test.WithVar(&NewFs, func() afero.Fs { return fs }))
By("Generate new shoot UID and write it to the host")
- b, err := NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, true)
+ b, err := NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, true)
Expect(err).NotTo(HaveOccurred())
uid := b.Shoot.GetInfo().Status.UID
@@ -121,7 +121,7 @@ metadata:
Expect(string(content)).To(Equal(string(uid)))
By("Do not regenerate shoot UID when file is present on host")
- b, err = NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, true)
+ b, err = NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, true)
Expect(err).NotTo(HaveOccurred())
Expect(b.Shoot.GetInfo().Status.UID).To(Equal(uid))
@@ -132,8 +132,8 @@ metadata:
})
When("not running the control plane (acting on the bootstrap cluster)", func() {
- It("should create a new Autonomous Botanist", func() {
- b, err := NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, false)
+ It("should create a new Self-Hosted Botanist", func() {
+ b, err := NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, false)
Expect(err).NotTo(HaveOccurred())
Expect(b.Shoot.CloudProfile.Name).To(Equal("stackit"))
@@ -143,11 +143,11 @@ metadata:
HaveField("ControllerRegistration.Name", "provider-stackit"),
HaveField("ControllerRegistration.Name", "dns-local"),
))
- Expect(b.Seed.GetInfo()).To(HaveField("ObjectMeta.Labels", Not(HaveKeyWithValue("seed.gardener.cloud/autonomous-shoot-cluster", "true"))))
+ Expect(b.Seed.GetInfo()).To(HaveField("ObjectMeta.Labels", Not(HaveKeyWithValue("seed.gardener.cloud/self-hosted-shoot-cluster", "true"))))
})
It("should use the technical ID as the control plane namespace", func() {
- b, err := NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, false)
+ b, err := NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, false)
Expect(err).NotTo(HaveOccurred())
Expect(b.Shoot.ControlPlaneNamespace).To(Equal("shoot--gardenadm--gardenadm"))
})
@@ -156,7 +156,7 @@ metadata:
fs := afero.NewMemMapFs()
DeferCleanup(test.WithVar(&NewFs, func() afero.Fs { return fs }))
- b, err := NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, false)
+ b, err := NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, false)
Expect(err).NotTo(HaveOccurred())
uid := b.Shoot.GetInfo().Status.UID
@@ -168,7 +168,7 @@ metadata:
})
It("should create the secrets with the fake garden client", func() {
- b, err := NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, false)
+ b, err := NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, false)
Expect(err).NotTo(HaveOccurred())
Expect(b.GardenClient.Get(ctx, client.ObjectKey{Name: "secret1"}, &corev1.Secret{})).To(Succeed())
@@ -177,7 +177,7 @@ metadata:
})
It("should create the secret binding and credentials binding", func() {
- b, err := NewAutonomousBotanistFromManifests(ctx, log, nil, configDir, true)
+ b, err := NewGardenadmBotanistFromManifests(ctx, log, nil, configDir, true)
Expect(err).NotTo(HaveOccurred())
Expect(b.GardenClient.Get(ctx, client.ObjectKey{Name: "provider-account"}, &corev1.Secret{})).To(Succeed())
diff --git a/pkg/gardenadm/botanist/controlplane.go b/pkg/gardenadm/botanist/controlplane.go
index 5e612fff149..97e58c0b639 100644
--- a/pkg/gardenadm/botanist/controlplane.go
+++ b/pkg/gardenadm/botanist/controlplane.go
@@ -49,10 +49,10 @@ import (
var PathKubeconfig = filepath.Join(string(filepath.Separator), "etc", "kubernetes", "admin.conf")
// KubeconfigSecretName is the name of the secret in the shoot namespace of the bootstrap cluster containing the
-// kubeconfig of the autonomous shoot.
+// kubeconfig of the self-hosted shoot.
const KubeconfigSecretName = "kubeconfig"
-func (b *AutonomousBotanist) deployETCD(role string) func(context.Context) error {
+func (b *GardenadmBotanist) deployETCD(role string) func(context.Context) error {
var portClient, portPeer, portMetrics int32 = 2379, 2380, 2381
if role == v1beta1constants.ETCDRoleEvents {
portClient, portPeer, portMetrics = etcdconstants.StaticPodPortEtcdEventsClient, 2383, 2384
@@ -74,7 +74,7 @@ func (b *AutonomousBotanist) deployETCD(role string) func(context.Context) error
}
}
-func (b *AutonomousBotanist) deployKubeAPIServer(ctx context.Context) error {
+func (b *GardenadmBotanist) deployKubeAPIServer(ctx context.Context) error {
b.Shoot.Components.ControlPlane.KubeAPIServer.EnableStaticTokenKubeconfig()
b.Shoot.Components.ControlPlane.KubeAPIServer.SetAutoscalingReplicas(ptr.To[int32](0))
@@ -102,7 +102,7 @@ type staticControlPlaneComponent struct {
mutate func(*corev1.Pod)
}
-func (b *AutonomousBotanist) staticControlPlaneComponents() []staticControlPlaneComponent {
+func (b *GardenadmBotanist) staticControlPlaneComponents() []staticControlPlaneComponent {
var (
components []staticControlPlaneComponent
@@ -147,7 +147,7 @@ func (b *AutonomousBotanist) staticControlPlaneComponents() []staticControlPlane
// DeployControlPlaneDeployments deploys the deployments for the static control plane components. It also updates the
// OperatingSystemConfig, waits for it to be reconciled by the OS extension, and deploys the ManagedResource containing
// the Secret with OperatingSystemConfig for gardener-node-agent.
-func (b *AutonomousBotanist) DeployControlPlaneDeployments(ctx context.Context) error {
+func (b *GardenadmBotanist) DeployControlPlaneDeployments(ctx context.Context) error {
if err := b.deployControlPlaneDeployments(ctx); err != nil {
return fmt.Errorf("failed deploying control plane deployments: %w", err)
}
@@ -171,7 +171,7 @@ func (b *AutonomousBotanist) DeployControlPlaneDeployments(ctx context.Context)
// WaitUntilControlPlaneDeploymentsReady waits until the control plane deployments are ready. It checks that the
// operating system config has been updated for all worker pools. In addition, it verifies that the static pod hashes
// match the desired hashes.
-func (b *AutonomousBotanist) WaitUntilControlPlaneDeploymentsReady(ctx context.Context) error {
+func (b *GardenadmBotanist) WaitUntilControlPlaneDeploymentsReady(ctx context.Context) error {
timeoutCtx, cancel := context.WithTimeout(ctx, botanist.GetTimeoutWaitOperatingSystemConfigUpdated(b.Shoot))
defer cancel()
@@ -201,7 +201,7 @@ func (b *AutonomousBotanist) WaitUntilControlPlaneDeploymentsReady(ctx context.C
return b.WaitUntilOperatingSystemConfigUpdatedForAllWorkerPools(ctx)
}
-func (b *AutonomousBotanist) deployControlPlaneDeployments(ctx context.Context) error {
+func (b *GardenadmBotanist) deployControlPlaneDeployments(ctx context.Context) error {
for _, component := range b.staticControlPlaneComponents() {
if err := b.deployControlPlaneComponent(ctx, component.deploy, component.targetObject, component.name); err != nil {
return fmt.Errorf("failed deploying %q: %w", component.name, err)
@@ -211,7 +211,7 @@ func (b *AutonomousBotanist) deployControlPlaneDeployments(ctx context.Context)
return nil
}
-func (b *AutonomousBotanist) deployControlPlaneComponent(ctx context.Context, deploy func(context.Context) error, targetObject client.Object, componentName string) error {
+func (b *GardenadmBotanist) deployControlPlaneComponent(ctx context.Context, deploy func(context.Context) error, targetObject client.Object, componentName string) error {
if err := deploy(ctx); err != nil {
return fmt.Errorf("failed deploying component %q: %w", componentName, err)
}
@@ -225,7 +225,7 @@ func (b *AutonomousBotanist) deployControlPlaneComponent(ctx context.Context, de
return b.SeedClientSet.Client().Get(ctx, client.ObjectKeyFromObject(targetObject), targetObject)
}
-func (b *AutonomousBotanist) populateStaticAdminTokenToAccessTokenSecret(ctx context.Context, componentName string) error {
+func (b *GardenadmBotanist) populateStaticAdminTokenToAccessTokenSecret(ctx context.Context, componentName string) error {
secret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: gardenerutils.SecretNamePrefixShootAccess + componentName, Namespace: b.Shoot.ControlPlaneNamespace}}
if err := b.SeedClientSet.Client().Get(ctx, client.ObjectKeyFromObject(secret), secret); err != nil {
if apierrors.IsNotFound(err) {
@@ -281,7 +281,7 @@ func (s staticPods) nameToHashMap() map[string]string {
return m
}
-func (b *AutonomousBotanist) staticControlPlanePods(ctx context.Context) (staticPods, error) {
+func (b *GardenadmBotanist) staticControlPlanePods(ctx context.Context) (staticPods, error) {
var pods staticPods
for _, component := range b.staticControlPlaneComponents() {
@@ -314,7 +314,7 @@ func NewClientSetFromFile(kubeconfigPath string, scheme *runtime.Scheme) (kubern
}
// CreateClientSet creates a client set for the control plane.
-func (b *AutonomousBotanist) CreateClientSet(ctx context.Context) (kubernetes.Interface, error) {
+func (b *GardenadmBotanist) CreateClientSet(ctx context.Context) (kubernetes.Interface, error) {
pathKubeconfig := PathKubeconfig
if path := os.Getenv("KUBECONFIG"); path != "" {
pathKubeconfig = path
@@ -354,7 +354,7 @@ func (b *AutonomousBotanist) CreateClientSet(ctx context.Context) (kubernetes.In
var NewWithConfig = kubernetes.NewWithConfig
// DiscoverKubernetesVersion discovers the Kubernetes version of the control plane.
-func (b *AutonomousBotanist) DiscoverKubernetesVersion(controlPlaneAddress string, caBundle []byte, token string) (*semver.Version, error) {
+func (b *GardenadmBotanist) DiscoverKubernetesVersion(controlPlaneAddress string, caBundle []byte, token string) (*semver.Version, error) {
clientSet, err := NewWithConfig(kubernetes.WithRESTConfig(&rest.Config{
Host: controlPlaneAddress,
TLSClientConfig: rest.TLSClientConfig{CAData: caBundle},
@@ -372,10 +372,10 @@ func (b *AutonomousBotanist) DiscoverKubernetesVersion(controlPlaneAddress strin
return version, nil
}
-// FetchKubeconfig fetches the kubeconfig of the autonomous shoot from the control plane machine via SSH and stores it
+// FetchKubeconfig fetches the kubeconfig of the self-hosted shoot from the control plane machine via SSH and stores it
// in a secret in the shoot namespace of the bootstrap cluster for later retrieval. It also writes the kubeconfig to the
// given output writer, if any.
-func (b *AutonomousBotanist) FetchKubeconfig(ctx context.Context, output io.Writer) error {
+func (b *GardenadmBotanist) FetchKubeconfig(ctx context.Context, output io.Writer) error {
kubeconfigBuffer := &bytes.Buffer{}
if err := b.sshConnection.SCP.CopyFromRemotePassThru(ctx, kubeconfigBuffer, PathKubeconfig, nil); err != nil {
return fmt.Errorf("error fetching kubeconfig: %w", err)
@@ -392,11 +392,11 @@ func (b *AutonomousBotanist) FetchKubeconfig(ctx context.Context, output io.Writ
if err != nil {
return fmt.Errorf("error writing kubeconfig secret: %w", err)
}
- b.Logger.Info("Stored kubeconfig of the autonomous shoot in secret", "namespace", kubeconfigSecret.Namespace, "name", kubeconfigSecret.Name)
+ b.Logger.Info("Stored kubeconfig of the self-hosted shoot in secret", "namespace", kubeconfigSecret.Namespace, "name", kubeconfigSecret.Name)
if output != nil {
if outputFile, ok := output.(*os.File); ok {
- b.Logger.Info("Writing kubeconfig of the autonomous shoot to file", "path", outputFile.Name())
+ b.Logger.Info("Writing kubeconfig of the self-hosted shoot to file", "path", outputFile.Name())
}
if _, err := output.Write(kubeconfigBytes); err != nil {
return fmt.Errorf("error writing kubeconfig to output: %w", err)
diff --git a/pkg/gardenadm/botanist/controlplane_test.go b/pkg/gardenadm/botanist/controlplane_test.go
index d103bead3fe..524157852cd 100644
--- a/pkg/gardenadm/botanist/controlplane_test.go
+++ b/pkg/gardenadm/botanist/controlplane_test.go
@@ -28,10 +28,10 @@ import (
)
var _ = Describe("ControlPlane", func() {
- var b *AutonomousBotanist
+ var b *GardenadmBotanist
BeforeEach(func() {
- b = &AutonomousBotanist{}
+ b = &GardenadmBotanist{}
})
Describe("#DiscoverKubernetesVersion", func() {
diff --git a/pkg/gardenadm/botanist/customresourcedefinitions.go b/pkg/gardenadm/botanist/customresourcedefinitions.go
index f350eb2d3bf..71fad7d1e5e 100644
--- a/pkg/gardenadm/botanist/customresourcedefinitions.go
+++ b/pkg/gardenadm/botanist/customresourcedefinitions.go
@@ -21,7 +21,7 @@ import (
)
// ReconcileCustomResourceDefinitions reconciles the custom resource definitions.
-func (b *AutonomousBotanist) ReconcileCustomResourceDefinitions(ctx context.Context) error {
+func (b *GardenadmBotanist) ReconcileCustomResourceDefinitions(ctx context.Context) error {
vpaCRDDeployer, err := vpa.NewCRD(b.SeedClientSet.Client(), nil)
if err != nil {
return fmt.Errorf("failed creating VPA CRD deployer: %w", err)
@@ -72,7 +72,7 @@ func (b *AutonomousBotanist) ReconcileCustomResourceDefinitions(ctx context.Cont
}
// EnsureCustomResourceDefinitionsReady ensures that the custom resource definitions are ready.
-func (b *AutonomousBotanist) EnsureCustomResourceDefinitionsReady(ctx context.Context) error {
+func (b *GardenadmBotanist) EnsureCustomResourceDefinitionsReady(ctx context.Context) error {
crdList := &apiextensionsv1.CustomResourceDefinitionList{}
if err := b.SeedClientSet.Client().List(ctx, crdList); err != nil {
return fmt.Errorf("failed to list CustomResourceDefinitions: %w", err)
diff --git a/pkg/gardenadm/botanist/customresourcedefinitions_test.go b/pkg/gardenadm/botanist/customresourcedefinitions_test.go
index f37373e8359..fa8295df3ce 100644
--- a/pkg/gardenadm/botanist/customresourcedefinitions_test.go
+++ b/pkg/gardenadm/botanist/customresourcedefinitions_test.go
@@ -34,7 +34,7 @@ var _ = Describe("CustomResourceDefinitions", func() {
fakeClient client.Client
- b *AutonomousBotanist
+ b *GardenadmBotanist
)
BeforeEach(func() {
@@ -46,7 +46,7 @@ var _ = Describe("CustomResourceDefinitions", func() {
mapper.Add(apiextensionsv1.SchemeGroupVersion.WithKind("CustomResourceDefinition"), meta.RESTScopeRoot)
applier := kubernetes.NewApplier(fakeClient, mapper)
- b = &AutonomousBotanist{
+ b = &GardenadmBotanist{
Botanist: &botanistpkg.Botanist{
Operation: &operation.Operation{
SeedClientSet: fakekubernetes.
@@ -125,7 +125,7 @@ var _ = Describe("CustomResourceDefinitions", func() {
})
})
- It("should deploy the additional CRDs for the medium-touch scenario", func() {
+ It("should deploy the additional CRDs for the managed infrastructure scenario", func() {
Expect(b.ReconcileCustomResourceDefinitions(ctx)).To(Succeed())
crdList := &apiextensionsv1.CustomResourceDefinitionList{}
diff --git a/pkg/gardenadm/botanist/dnsrecord.go b/pkg/gardenadm/botanist/dnsrecord.go
index ba5bffd2030..f06cbc17911 100644
--- a/pkg/gardenadm/botanist/dnsrecord.go
+++ b/pkg/gardenadm/botanist/dnsrecord.go
@@ -12,10 +12,10 @@ import (
)
// DeployBootstrapDNSRecord deploys the external DNSRecord pointing to the first control plane machine for bootstrapping
-// the autonomous shoot cluster. The DNSRecord might be publicly resolvable but not publicly accessible, depending on
+// the self-hosted shoot cluster. The DNSRecord might be publicly resolvable but not publicly accessible, depending on
// shoot's infrastructure provider and network setup. It should be resolvable and accessible from within the shoot
// cluster's network including the machines, so `gardenadm init` can use it to bootstrap the cluster.
-func (b *AutonomousBotanist) DeployBootstrapDNSRecord(ctx context.Context) error {
+func (b *GardenadmBotanist) DeployBootstrapDNSRecord(ctx context.Context) error {
machine, err := b.GetMachineByIndex(0)
if err != nil {
return err
diff --git a/pkg/gardenadm/botanist/etcd.go b/pkg/gardenadm/botanist/etcd.go
index c4f1fcdbad8..4b5fd1b4bcb 100644
--- a/pkg/gardenadm/botanist/etcd.go
+++ b/pkg/gardenadm/botanist/etcd.go
@@ -35,7 +35,7 @@ import (
)
// DeployEtcdDruid deploys the etcd-druid component.
-func (b *AutonomousBotanist) DeployEtcdDruid(ctx context.Context) error {
+func (b *GardenadmBotanist) DeployEtcdDruid(ctx context.Context) error {
var componentImageVectors imagevectorutils.ComponentImageVectors
if path := os.Getenv(imagevectorutils.ComponentOverrideEnv); path != "" {
var err error
@@ -67,7 +67,7 @@ func (b *AutonomousBotanist) DeployEtcdDruid(ctx context.Context) error {
}
// ReconcileBackupBucket reconciles the core.gardener.cloud/v1beta1.BackupBucket resource for the shoot cluster.
-func (b *AutonomousBotanist) ReconcileBackupBucket(ctx context.Context) error {
+func (b *GardenadmBotanist) ReconcileBackupBucket(ctx context.Context) error {
backupBucket, err := b.reconcileCoreBackupBucketResource(ctx)
if err != nil {
return fmt.Errorf("failed reconciling core.gardener.cloud/v1beta1.BackupBucket resource: %w", err)
@@ -90,7 +90,7 @@ func (b *AutonomousBotanist) ReconcileBackupBucket(ctx context.Context) error {
})
}
-func (b *AutonomousBotanist) reconcileCoreBackupBucketResource(ctx context.Context) (*gardencorev1beta1.BackupBucket, error) {
+func (b *GardenadmBotanist) reconcileCoreBackupBucketResource(ctx context.Context) (*gardencorev1beta1.BackupBucket, error) {
component := corebackupbucket.New(b.Logger, b.GardenClient, &corebackupbucket.Values{
Name: string(b.Shoot.GetInfo().Status.UID),
Config: v1beta1helper.GetBackupConfigForShoot(b.Shoot.GetInfo(), nil),
@@ -106,7 +106,7 @@ func (b *AutonomousBotanist) reconcileCoreBackupBucketResource(ctx context.Conte
}
// ReconcileBackupEntry reconciles the core.gardener.cloud/v1beta1.BackupEntry resource for the shoot cluster.
-func (b *AutonomousBotanist) ReconcileBackupEntry(ctx context.Context) error {
+func (b *GardenadmBotanist) ReconcileBackupEntry(ctx context.Context) error {
backupEntry, err := b.reconcileCoreBackupEntryResource(ctx)
if err != nil {
return fmt.Errorf("failed reconciling core.gardener.cloud/v1beta1.BackupEntry resource: %w", err)
@@ -129,7 +129,7 @@ func (b *AutonomousBotanist) ReconcileBackupEntry(ctx context.Context) error {
})
}
-func (b *AutonomousBotanist) reconcileCoreBackupEntryResource(ctx context.Context) (*gardencorev1beta1.BackupEntry, error) {
+func (b *GardenadmBotanist) reconcileCoreBackupEntryResource(ctx context.Context) (*gardencorev1beta1.BackupEntry, error) {
if err := b.Shoot.Components.BackupEntry.Deploy(ctx); err != nil {
return nil, fmt.Errorf("failed reconciling core.gardener.cloud/v1beta1.BackupEntry resource: %w", err)
}
@@ -161,7 +161,7 @@ func runReconcilerUntilCondition(ctx context.Context, logger logr.Logger, contro
// WaitUntilEtcdsReconciled waits until the druid.gardener.cloud/v1alpha1.Etcd resources have been reconciled by
// etcd-druid.
-func (b *AutonomousBotanist) WaitUntilEtcdsReconciled(ctx context.Context) error {
+func (b *GardenadmBotanist) WaitUntilEtcdsReconciled(ctx context.Context) error {
if err := b.WaitUntilEtcdsReady(ctx); err != nil {
return fmt.Errorf("failed waiting for etcd to become ready: %w", err)
}
@@ -172,7 +172,7 @@ func (b *AutonomousBotanist) WaitUntilEtcdsReconciled(ctx context.Context) error
// FinalizeEtcdBootstrapTransition cleans up no longer needed directories for the bootstrap etcds. Those are not deleted
// automatically.
-func (b *AutonomousBotanist) FinalizeEtcdBootstrapTransition(_ context.Context) error {
+func (b *GardenadmBotanist) FinalizeEtcdBootstrapTransition(_ context.Context) error {
for _, dir := range []string{
filepath.Join(string(filepath.Separator), "var", "lib", bootstrapetcd.Name(v1beta1constants.ETCDRoleMain)),
filepath.Join(string(filepath.Separator), "var", "lib", bootstrapetcd.Name(v1beta1constants.ETCDRoleEvents)),
diff --git a/pkg/gardenadm/botanist/extensions.go b/pkg/gardenadm/botanist/extensions.go
index d9069f719e1..e6339663e7d 100644
--- a/pkg/gardenadm/botanist/extensions.go
+++ b/pkg/gardenadm/botanist/extensions.go
@@ -84,31 +84,29 @@ func ComputeExtensions(resources gardenadm.Resources, runsControlPlane, managedI
return extensions, nil
}
-// wantedExtensionKinds returns the set of extension kinds that are needed and supported for autonomous shoot clusters.
+// wantedExtensionKinds returns the set of extension kinds that are needed and supported for self-hosted shoot clusters.
// runsControlPlane indicates whether we are bootstrapping the control plane of the cluster (i.e., when executing
// `gardenadm init`).
-// managedInfrastructure indicates whether the infrastructure of the shoot cluster is managed by Gardener (medium-touch
-// scenario) or not (high-touch scenario).
func wantedExtensionKinds(runsControlPlane, managedInfrastructure bool) sets.Set[string] {
if !runsControlPlane {
// When running `gardenadm bootstrap` against the bootstrap cluster, we create Infrastructure, OSC, Worker, and
- // DNSRecord for the control plane of the autonomous shoot cluster, so we only need to deploy a subset of the
+ // DNSRecord for the control plane of the self-hosted shoot cluster, so we only need to deploy a subset of the
// extensions required for the shoot.
return sets.New[string](extensionsv1alpha1.InfrastructureResource, extensionsv1alpha1.OperatingSystemConfigResource, extensionsv1alpha1.WorkerResource, extensionsv1alpha1.DNSRecordResource)
}
- // In the high-touch scenario, we don't deploy Infrastructure, Worker, and DNSRecord extensions because they are
- // managed outside of Gardener.
+ // In the "unmanaged infrastructure" scenario, we don't deploy Infrastructure, Worker, and DNSRecord extensions
+ // because they are managed outside of Gardener.
if !managedInfrastructure {
return extensionsv1alpha1.AllExtensionKinds.Clone().Delete(extensionsv1alpha1.InfrastructureResource, extensionsv1alpha1.WorkerResource, extensionsv1alpha1.DNSRecordResource)
}
- // In `gardenadm init`, we deploy all extensions referenced by the shoot in the medium-touch scenario.
+ // In `gardenadm init`, we deploy all extensions referenced by the shoot in the "managed infrastructure" scenario.
return extensionsv1alpha1.AllExtensionKinds.Clone()
}
-// computeWantedControllerRegistrationNames returns the names of all ControllerRegistrations relevant for the autonomous
-// botanist based on the parsed manifests and the wanted extension kinds.
+// computeWantedControllerRegistrationNames returns the names of all ControllerRegistrations relevant for the
+// gardenadm botanist based on the parsed manifests and the wanted extension kinds.
func computeWantedControllerRegistrationNames(resources gardenadm.Resources, wantedExtensionKinds sets.Set[string]) (sets.Set[string], error) {
var (
result = sets.New[string]()
@@ -164,7 +162,7 @@ func controllerRegistrationSliceToList(controllerRegistrations []*gardencorev1be
// ReconcileExtensionControllerInstallations reconciles the ControllerInstallation resources necessary to deploy the
// extension controllers.
-func (b *AutonomousBotanist) ReconcileExtensionControllerInstallations(ctx context.Context, bootstrapMode bool) error {
+func (b *GardenadmBotanist) ReconcileExtensionControllerInstallations(ctx context.Context, bootstrapMode bool) error {
reconciler := controllerinstallation.Reconciler{
GardenClient: b.GardenClient,
SeedClientSet: b.SeedClientSet,
@@ -193,7 +191,7 @@ var TimeoutManagedResourceHealthCheck = 2 * time.Minute
// WaitUntilExtensionControllerInstallationsHealthy waits until all ControllerInstallation resources used for
// extension controller deployments are healthy.
-func (b *AutonomousBotanist) WaitUntilExtensionControllerInstallationsHealthy(ctx context.Context) error {
+func (b *GardenadmBotanist) WaitUntilExtensionControllerInstallationsHealthy(ctx context.Context) error {
var taskFns []flow.TaskFn
for _, extension := range b.Extensions {
diff --git a/pkg/gardenadm/botanist/extensions_test.go b/pkg/gardenadm/botanist/extensions_test.go
index 50fbe3c707b..d9b415b04c5 100644
--- a/pkg/gardenadm/botanist/extensions_test.go
+++ b/pkg/gardenadm/botanist/extensions_test.go
@@ -230,7 +230,7 @@ var _ = Describe("Extensions", func() {
})
When("running the control plane (gardenadm init)", func() {
- When("infrastructure is managed outside of Gardener (high-touch)", func() {
+ When("infrastructure is not managed by Gardener", func() {
It("should return all extensions referenced by shoot (except Infrastructure, Worker, and DNSRecord)", func() {
Expect(ComputeExtensions(resources, true, false)).To(ConsistOf(
And(
@@ -249,7 +249,7 @@ var _ = Describe("Extensions", func() {
})
})
- When("infrastructure is managed by Gardener (medium-touch)", func() {
+ When("infrastructure is managed by Gardener", func() {
It("should return all extensions referenced by shoot", func() {
Expect(ComputeExtensions(resources, true, true)).To(ConsistOf(
And(
@@ -305,7 +305,7 @@ var _ = Describe("Extensions", func() {
extension2 = "ext2"
fakeClient client.Client
- b *AutonomousBotanist
+ b *GardenadmBotanist
managedResource1 *resourcesv1alpha1.ManagedResource
managedResource2 *resourcesv1alpha1.ManagedResource
@@ -313,7 +313,7 @@ var _ = Describe("Extensions", func() {
BeforeEach(func() {
fakeClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).WithStatusSubresource(&resourcesv1alpha1.ManagedResource{}).Build()
- b = &AutonomousBotanist{
+ b = &GardenadmBotanist{
Botanist: &botanistpkg.Botanist{
Operation: &operation.Operation{
SeedClientSet: fakekubernetes.NewClientSetBuilder().WithClient(fakeClient).Build(),
diff --git a/pkg/gardenadm/botanist/kubelet.go b/pkg/gardenadm/botanist/kubelet.go
index 2c9286a4589..09a72e670b0 100644
--- a/pkg/gardenadm/botanist/kubelet.go
+++ b/pkg/gardenadm/botanist/kubelet.go
@@ -21,7 +21,7 @@ import (
const kubeletTokenFilePermission = 0o600
// WriteKubeletBootstrapKubeconfig writes the kubelet bootstrap kubeconfig to the file system.
-func (b *AutonomousBotanist) WriteKubeletBootstrapKubeconfig(ctx context.Context) error {
+func (b *GardenadmBotanist) WriteKubeletBootstrapKubeconfig(ctx context.Context) error {
if err := b.ensureGardenerNodeAgentDirectories(); err != nil {
return fmt.Errorf("failed ensuring gardener-node-agent directories exist: %w", err)
}
diff --git a/pkg/gardenadm/botanist/kubelet_test.go b/pkg/gardenadm/botanist/kubelet_test.go
index 9e331a7bc0e..b9479ee9e32 100644
--- a/pkg/gardenadm/botanist/kubelet_test.go
+++ b/pkg/gardenadm/botanist/kubelet_test.go
@@ -40,7 +40,7 @@ var _ = Describe("Kubelet", func() {
fakeSecretManager secretsmanager.Interface
fakeDBus *fakedbus.DBus
- b *AutonomousBotanist
+ b *GardenadmBotanist
)
BeforeEach(func() {
@@ -52,7 +52,7 @@ var _ = Describe("Kubelet", func() {
fakeSecretManager = fakesecretsmanager.New(fakeSeedClient, namespace)
fakeDBus = fakedbus.New()
- b = &AutonomousBotanist{
+ b = &GardenadmBotanist{
Botanist: &botanistpkg.Botanist{
Operation: &operation.Operation{
Logger: logr.Discard(),
diff --git a/pkg/gardenadm/botanist/machines.go b/pkg/gardenadm/botanist/machines.go
index e5df7b28238..e103dc75851 100644
--- a/pkg/gardenadm/botanist/machines.go
+++ b/pkg/gardenadm/botanist/machines.go
@@ -16,7 +16,7 @@ import (
// ListControlPlaneMachines stores all control plane machines in controlPlaneMachines for later retrieval.
// Listing the machines only once ensures consistent ordering when accessing them by index.
-func (b *AutonomousBotanist) ListControlPlaneMachines(ctx context.Context) error {
+func (b *GardenadmBotanist) ListControlPlaneMachines(ctx context.Context) error {
machineList := &machinev1alpha1.MachineList{}
if err := b.SeedClientSet.Client().List(ctx, machineList, client.InNamespace(b.Shoot.ControlPlaneNamespace)); err != nil {
return fmt.Errorf("failed to list machines: %w", err)
@@ -26,7 +26,7 @@ func (b *AutonomousBotanist) ListControlPlaneMachines(ctx context.Context) error
}
// GetMachineByIndex returns the control plane machine with the given index or an error if the index is out of bounds.
-func (b *AutonomousBotanist) GetMachineByIndex(index int) (*machinev1alpha1.Machine, error) {
+func (b *GardenadmBotanist) GetMachineByIndex(index int) (*machinev1alpha1.Machine, error) {
if index < 0 {
return nil, fmt.Errorf("machine index must be non-negative, got %d", index)
}
diff --git a/pkg/gardenadm/botanist/network.go b/pkg/gardenadm/botanist/network.go
index 0e96ce92e32..caf007a99ef 100644
--- a/pkg/gardenadm/botanist/network.go
+++ b/pkg/gardenadm/botanist/network.go
@@ -27,7 +27,7 @@ import (
// IsPodNetworkAvailable checks if the ManagedResource for CoreDNS is deployed and ready. If yes, pod network must be
// available. Otherwise, CoreDNS which runs in this network wouldn't be available.
-func (b *AutonomousBotanist) IsPodNetworkAvailable(ctx context.Context) (bool, error) {
+func (b *GardenadmBotanist) IsPodNetworkAvailable(ctx context.Context) (bool, error) {
managedResource := &resourcesv1alpha1.ManagedResource{ObjectMeta: metav1.ObjectMeta{Name: coredns.ManagedResourceName, Namespace: b.Shoot.ControlPlaneNamespace}}
if err := b.SeedClientSet.Client().Get(ctx, client.ObjectKeyFromObject(managedResource), managedResource); err != nil {
if meta.IsNoMatchError(err) || apierrors.IsNotFound(err) {
@@ -39,7 +39,7 @@ func (b *AutonomousBotanist) IsPodNetworkAvailable(ctx context.Context) (bool, e
}
// ApplyNetworkPolicies reconciles all namespaces in the cluster in order to apply the network policies.
-func (b *AutonomousBotanist) ApplyNetworkPolicies(ctx context.Context) error {
+func (b *GardenadmBotanist) ApplyNetworkPolicies(ctx context.Context) error {
reconciler := &networkpolicy.Reconciler{
RuntimeClient: b.SeedClientSet.Client(),
Resolver: hostnameresolver.NewNoOpProvider(),
diff --git a/pkg/gardenadm/botanist/network_test.go b/pkg/gardenadm/botanist/network_test.go
index 4e678f7fcfd..1d6944eb9f5 100644
--- a/pkg/gardenadm/botanist/network_test.go
+++ b/pkg/gardenadm/botanist/network_test.go
@@ -31,13 +31,13 @@ var _ = Describe("Network", func() {
ctx context.Context
namespaceName = "kube-system"
- b *AutonomousBotanist
+ b *GardenadmBotanist
)
BeforeEach(func() {
ctx = context.Background()
- b = &AutonomousBotanist{
+ b = &GardenadmBotanist{
Botanist: &botanistpkg.Botanist{
Operation: &operation.Operation{
Shoot: &shoot.Shoot{
diff --git a/pkg/gardenadm/botanist/nodeagent.go b/pkg/gardenadm/botanist/nodeagent.go
index 65e5564411d..bd8988c46ce 100644
--- a/pkg/gardenadm/botanist/nodeagent.go
+++ b/pkg/gardenadm/botanist/nodeagent.go
@@ -36,7 +36,7 @@ import (
// WriteBootstrapToken creates a bootstrap token for the gardener-node-agent and kubelet, and writes it to the file
// system.
-func (b *AutonomousBotanist) WriteBootstrapToken(ctx context.Context) error {
+func (b *GardenadmBotanist) WriteBootstrapToken(ctx context.Context) error {
bootstrapTokenSecret, err := bootstraptoken.ComputeBootstrapToken(
ctx,
b.SeedClientSet.Client(),
@@ -57,7 +57,7 @@ func emptyTemporaryClusterAdminBinding() *rbacv1.ClusterRoleBinding {
return &rbacv1.ClusterRoleBinding{ObjectMeta: metav1.ObjectMeta{Name: "zzz-temporary-cluster-admin-access-for-bootstrapping"}}
}
-func (b *AutonomousBotanist) reconcileTemporaryClusterAdminBindingForBootstrapping(ctx context.Context) error {
+func (b *GardenadmBotanist) reconcileTemporaryClusterAdminBindingForBootstrapping(ctx context.Context) error {
clusterRoleBinding := emptyTemporaryClusterAdminBinding()
_, err := controllerutil.CreateOrUpdate(ctx, b.SeedClientSet.Client(), clusterRoleBinding, func() error {
clusterRoleBinding.RoleRef = rbacv1.RoleRef{
@@ -96,7 +96,7 @@ func (b *AutonomousBotanist) reconcileTemporaryClusterAdminBindingForBootstrappi
// Finally, as the kubelet has already been started earlier such that it can run the static control plane pods, this
// made it create the real kubeconfig file. We have to actively delete it in order to re-trigger its bootstrap process
// w/ the bootstrap token (otherwise, it tries to use this real kubeconfig file and fails).
-func (b *AutonomousBotanist) ActivateGardenerNodeAgent(ctx context.Context) error {
+func (b *GardenadmBotanist) ActivateGardenerNodeAgent(ctx context.Context) error {
alreadyBootstrapped, err := b.FS.Exists(nodeagentconfigv1alpha1.KubeconfigFilePath)
if err != nil {
return fmt.Errorf("failed checking whether gardener-node-agent's kubeconfig %s exists: %w", nodeagentconfigv1alpha1.KubeconfigFilePath, err)
@@ -125,7 +125,7 @@ func (b *AutonomousBotanist) ActivateGardenerNodeAgent(ctx context.Context) erro
}
// ApproveNodeAgentCertificateSigningRequest approves the node agent certificate signing request.
-func (b *AutonomousBotanist) ApproveNodeAgentCertificateSigningRequest(ctx context.Context) error {
+func (b *GardenadmBotanist) ApproveNodeAgentCertificateSigningRequest(ctx context.Context) error {
bootstrapToken, err := b.FS.ReadFile(nodeagentconfigv1alpha1.BootstrapTokenFilePath)
if err != nil {
if !errors.Is(err, afero.ErrFileNotFound) {
@@ -178,7 +178,7 @@ func (b *AutonomousBotanist) ApproveNodeAgentCertificateSigningRequest(ctx conte
// FinalizeGardenerNodeAgentBootstrapping deletes the temporary cluster-admin ClusterRoleBinding for
// gardener-node-agent.
-func (b *AutonomousBotanist) FinalizeGardenerNodeAgentBootstrapping(ctx context.Context) error {
+func (b *GardenadmBotanist) FinalizeGardenerNodeAgentBootstrapping(ctx context.Context) error {
return kubernetesutils.DeleteObject(ctx, b.SeedClientSet.Client(), emptyTemporaryClusterAdminBinding())
}
@@ -194,7 +194,7 @@ var (
// WaitUntilGardenerNodeAgentLeaseIsRenewed waits until the gardener-node-agent lease is renewed, which indicates that
// it is ready to be used (and that it still has the needed permissions, even though its cluster-admin binding has been
// removed).
-func (b *AutonomousBotanist) WaitUntilGardenerNodeAgentLeaseIsRenewed(ctx context.Context) error {
+func (b *GardenadmBotanist) WaitUntilGardenerNodeAgentLeaseIsRenewed(ctx context.Context) error {
node, err := nodeagent.FetchNodeByHostName(ctx, b.SeedClientSet.Client(), b.HostName)
if err != nil {
return fmt.Errorf("failed fetching node object by hostname %q: %w", b.HostName, err)
diff --git a/pkg/gardenadm/botanist/nodeagent_test.go b/pkg/gardenadm/botanist/nodeagent_test.go
index 7a9f37e9699..4f83db7d244 100644
--- a/pkg/gardenadm/botanist/nodeagent_test.go
+++ b/pkg/gardenadm/botanist/nodeagent_test.go
@@ -56,7 +56,7 @@ var _ = Describe("NodeAgent", func() {
fakeFS afero.Afero
fakeClock *testclock.FakeClock
- b *AutonomousBotanist
+ b *GardenadmBotanist
)
BeforeEach(func() {
@@ -75,7 +75,7 @@ var _ = Describe("NodeAgent", func() {
fakeFS = afero.Afero{Fs: afero.NewMemMapFs()}
fakeClock = testclock.NewFakeClock(time.Now())
- b = &AutonomousBotanist{
+ b = &GardenadmBotanist{
Botanist: &botanistpkg.Botanist{
Operation: &operation.Operation{
Logger: logr.Discard(),
diff --git a/pkg/gardenadm/botanist/operatingsystemconfig.go b/pkg/gardenadm/botanist/operatingsystemconfig.go
index d9d33134ac9..dff9bc4897e 100644
--- a/pkg/gardenadm/botanist/operatingsystemconfig.go
+++ b/pkg/gardenadm/botanist/operatingsystemconfig.go
@@ -40,7 +40,7 @@ import (
// DeployOperatingSystemConfigSecretForBootstrap deploys the OperatingSystemConfig resource and adds its content into
// a Secret so that gardener-node-agent can read it and reconcile its content.
-func (b *AutonomousBotanist) DeployOperatingSystemConfigSecretForBootstrap(ctx context.Context) error {
+func (b *GardenadmBotanist) DeployOperatingSystemConfigSecretForBootstrap(ctx context.Context) error {
if err := b.deployControlPlaneDeployments(ctx); err != nil {
return fmt.Errorf("failed deploying control plane deployments: %w", err)
}
@@ -53,7 +53,7 @@ func (b *AutonomousBotanist) DeployOperatingSystemConfigSecretForBootstrap(ctx c
return b.createOperatingSystemConfigSecretForNodeAgent(ctx, oscData.Object, oscData.GardenerNodeAgentSecretName, controlPlaneWorkerPoolName)
}
-func (b *AutonomousBotanist) createOperatingSystemConfigSecretForNodeAgent(ctx context.Context, osc *extensionsv1alpha1.OperatingSystemConfig, secretName, poolName string) error {
+func (b *GardenadmBotanist) createOperatingSystemConfigSecretForNodeAgent(ctx context.Context, osc *extensionsv1alpha1.OperatingSystemConfig, secretName, poolName string) error {
var err error
b.operatingSystemConfigSecret, err = nodeagentcomponent.OperatingSystemConfigSecret(ctx, b.SeedClientSet.Client(), osc, secretName, poolName)
@@ -64,7 +64,7 @@ func (b *AutonomousBotanist) createOperatingSystemConfigSecretForNodeAgent(ctx c
return b.SeedClientSet.Client().Create(ctx, b.operatingSystemConfigSecret)
}
-func (b *AutonomousBotanist) appendAdminKubeconfigToFiles(files []extensionsv1alpha1.File) ([]extensionsv1alpha1.File, error) {
+func (b *GardenadmBotanist) appendAdminKubeconfigToFiles(files []extensionsv1alpha1.File) ([]extensionsv1alpha1.File, error) {
userKubeconfigSecret, ok := b.SecretsManager.Get(kubeapiserver.SecretNameUserKubeconfig)
if !ok {
return nil, fmt.Errorf("failed fetching secret %q", kubeapiserver.SecretNameUserKubeconfig)
@@ -77,7 +77,7 @@ func (b *AutonomousBotanist) appendAdminKubeconfigToFiles(files []extensionsv1al
}), nil
}
-func (b *AutonomousBotanist) deployOperatingSystemConfig(ctx context.Context) (*operatingsystemconfig.Data, string, error) {
+func (b *GardenadmBotanist) deployOperatingSystemConfig(ctx context.Context) (*operatingsystemconfig.Data, string, error) {
pods, err := b.staticControlPlanePods(ctx)
if err != nil {
return nil, "", fmt.Errorf("failed computing files for static control plane pods: %w", err)
@@ -115,7 +115,7 @@ func (b *AutonomousBotanist) deployOperatingSystemConfig(ctx context.Context) (*
// ApplyOperatingSystemConfig runs gardener-node-agent's reconciliation logic in order to apply the
// OperatingSystemConfig.
-func (b *AutonomousBotanist) ApplyOperatingSystemConfig(ctx context.Context) error {
+func (b *GardenadmBotanist) ApplyOperatingSystemConfig(ctx context.Context) error {
if b.operatingSystemConfigSecret == nil {
return fmt.Errorf("operating system config secret is nil, make sure to call createOperatingSystemConfigSecretForNodeAgent() first")
}
@@ -152,7 +152,7 @@ func (b *AutonomousBotanist) ApplyOperatingSystemConfig(ctx context.Context) err
return err
}
-func (b *AutonomousBotanist) ensureGardenerNodeAgentDirectories() error {
+func (b *GardenadmBotanist) ensureGardenerNodeAgentDirectories() error {
if err := b.FS.MkdirAll(nodeagentconfigv1alpha1.TempDir, os.ModeDir); err != nil {
return fmt.Errorf("failed creating temporary directory (%q): %w", nodeagentconfigv1alpha1.TempDir, err)
}
@@ -164,7 +164,7 @@ func (b *AutonomousBotanist) ensureGardenerNodeAgentDirectories() error {
// PrepareGardenerNodeInitConfiguration creates a Secret containing an OperatingSystemConfig with the gardener-node-init
// unit.
-func (b *AutonomousBotanist) PrepareGardenerNodeInitConfiguration(ctx context.Context, secretName, controlPlaneAddress string, caBundle []byte, bootstrapToken string) error {
+func (b *GardenadmBotanist) PrepareGardenerNodeInitConfiguration(ctx context.Context, secretName, controlPlaneAddress string, caBundle []byte, bootstrapToken string) error {
osc, err := b.generateGardenerNodeInitOperatingSystemConfig(secretName, controlPlaneAddress, bootstrapToken, caBundle)
if err != nil {
return fmt.Errorf("failed computing units and files for gardener-node-init: %w", err)
@@ -173,7 +173,7 @@ func (b *AutonomousBotanist) PrepareGardenerNodeInitConfiguration(ctx context.Co
return b.createOperatingSystemConfigSecretForNodeAgent(ctx, osc, secretName, "")
}
-func (b *AutonomousBotanist) generateGardenerNodeInitOperatingSystemConfig(secretName, controlPlaneAddress, bootstrapToken string, caBundle []byte) (*extensionsv1alpha1.OperatingSystemConfig, error) {
+func (b *GardenadmBotanist) generateGardenerNodeInitOperatingSystemConfig(secretName, controlPlaneAddress, bootstrapToken string, caBundle []byte) (*extensionsv1alpha1.OperatingSystemConfig, error) {
image, err := imagevector.Containers().FindImage(imagevector.ContainerImageNameGardenerNodeAgent)
if err != nil {
return nil, fmt.Errorf("failed finding image %q: %w", imagevector.ContainerImageNameGardenerNodeAgent, err)
@@ -207,7 +207,7 @@ func (b *AutonomousBotanist) generateGardenerNodeInitOperatingSystemConfig(secre
}
// IsGardenerNodeAgentInitialized returns true if the gardener-node-agent systemd unit exists.
-func (b *AutonomousBotanist) IsGardenerNodeAgentInitialized(ctx context.Context) (bool, error) {
+func (b *GardenadmBotanist) IsGardenerNodeAgentInitialized(ctx context.Context) (bool, error) {
unitStatuses, err := b.DBus.List(ctx)
if err != nil {
return false, fmt.Errorf("failed listing systemd units: %w", err)
@@ -229,7 +229,7 @@ func (b *AutonomousBotanist) IsGardenerNodeAgentInitialized(ctx context.Context)
// ControlPlaneBootstrapOperatingSystemConfig creates the deployer for the OperatingSystemConfig custom resource that is
// used for bootstrapping control plane nodes in `gardenadm bootstrap`.
-func (b *AutonomousBotanist) ControlPlaneBootstrapOperatingSystemConfig() (operatingsystemconfig.Interface, error) {
+func (b *GardenadmBotanist) ControlPlaneBootstrapOperatingSystemConfig() (operatingsystemconfig.Interface, error) {
image, err := imagevector.Containers().FindImage(imagevector.ContainerImageNameGardenadm)
if err != nil {
return nil, fmt.Errorf("failed finding image %q: %w", imagevector.ContainerImageNameGardenadm, err)
diff --git a/pkg/gardenadm/botanist/operatingsystemconfig_test.go b/pkg/gardenadm/botanist/operatingsystemconfig_test.go
index 94c3548c544..8564373d9c1 100644
--- a/pkg/gardenadm/botanist/operatingsystemconfig_test.go
+++ b/pkg/gardenadm/botanist/operatingsystemconfig_test.go
@@ -34,7 +34,7 @@ import (
var _ = Describe("OperatingSystemConfig", func() {
var (
ctx = context.Background()
- b *AutonomousBotanist
+ b *GardenadmBotanist
fs afero.Afero
fakeDBus *fakedbus.DBus
@@ -48,7 +48,7 @@ var _ = Describe("OperatingSystemConfig", func() {
fakeClient = fakeclient.NewClientBuilder().Build()
clientSet = fakekubernetes.NewClientSetBuilder().WithClient(fakeClient).Build()
- b = &AutonomousBotanist{
+ b = &GardenadmBotanist{
FS: fs,
DBus: fakeDBus,
HostName: "foo-host",
diff --git a/pkg/gardenadm/botanist/secrets.go b/pkg/gardenadm/botanist/secrets.go
index 959d2b3829c..28bb15599de 100644
--- a/pkg/gardenadm/botanist/secrets.go
+++ b/pkg/gardenadm/botanist/secrets.go
@@ -16,7 +16,7 @@ import (
)
// MigrateSecrets exports the secrets generated with the fake client and imports them with the real client.
-func (b *AutonomousBotanist) MigrateSecrets(ctx context.Context, fakeClient, realClient client.Client) error {
+func (b *GardenadmBotanist) MigrateSecrets(ctx context.Context, fakeClient, realClient client.Client) error {
secretList := &corev1.SecretList{}
if err := fakeClient.List(ctx, secretList, client.InNamespace(b.Shoot.ControlPlaneNamespace)); err != nil {
return fmt.Errorf("failed listing secrets with fake client: %w", err)
diff --git a/pkg/gardenadm/botanist/secrets_test.go b/pkg/gardenadm/botanist/secrets_test.go
index 94785709337..94a66c89932 100644
--- a/pkg/gardenadm/botanist/secrets_test.go
+++ b/pkg/gardenadm/botanist/secrets_test.go
@@ -30,7 +30,7 @@ var _ = Describe("Secrets", func() {
fakeClient1 client.Client
fakeClient2 client.Client
- b *AutonomousBotanist
+ b *GardenadmBotanist
)
BeforeEach(func() {
@@ -39,7 +39,7 @@ var _ = Describe("Secrets", func() {
fakeClient1 = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
fakeClient2 = fakeclient.NewClientBuilder().WithScheme(kubernetes.SeedScheme).Build()
- b = &AutonomousBotanist{
+ b = &GardenadmBotanist{
Botanist: &botanistpkg.Botanist{
Operation: &operation.Operation{
SeedClientSet: fakekubernetes.
diff --git a/pkg/gardenadm/botanist/ssh.go b/pkg/gardenadm/botanist/ssh.go
index f9b5a51923e..7d4bf6e7a49 100644
--- a/pkg/gardenadm/botanist/ssh.go
+++ b/pkg/gardenadm/botanist/ssh.go
@@ -26,8 +26,8 @@ import (
)
// ConnectToControlPlaneMachine opens an SSH connection via the Bastion to the first control plane machine of the
-// autonomous shoot. The connection is stored in the sshConnection field.
-func (b *AutonomousBotanist) ConnectToControlPlaneMachine(ctx context.Context) error {
+// self-hosted shoot. The connection is stored in the sshConnection field.
+func (b *GardenadmBotanist) ConnectToControlPlaneMachine(ctx context.Context) error {
machine, err := b.GetMachineByIndex(0)
if err != nil {
return err
@@ -61,7 +61,7 @@ func (b *AutonomousBotanist) ConnectToControlPlaneMachine(ctx context.Context) e
}
// SSHConnection returns the SSH connection to the control plane machine opened by ConnectToControlPlaneMachine.
-func (b *AutonomousBotanist) SSHConnection() *sshutils.Connection {
+func (b *GardenadmBotanist) SSHConnection() *sshutils.Connection {
return b.sshConnection
}
@@ -78,7 +78,7 @@ var (
)
// CopyManifests copies all manifests needed for `gardenadm init` to the remote machine under GardenadmBaseDir.
-func (b *AutonomousBotanist) CopyManifests(ctx context.Context, configDir fs.FS) error {
+func (b *GardenadmBotanist) CopyManifests(ctx context.Context, configDir fs.FS) error {
if err := prepareRemoteDirs(ctx, b.sshConnection); err != nil {
return err
}
@@ -135,7 +135,7 @@ func copyImageVectorOverride(ctx context.Context, conn *sshutils.Connection) (er
return nil
}
-func (b *AutonomousBotanist) copyShootState(ctx context.Context) error {
+func (b *GardenadmBotanist) copyShootState(ctx context.Context) error {
shootState := &gardencorev1beta1.ShootState{}
if err := b.GardenClient.Get(ctx, client.ObjectKeyFromObject(b.Shoot.GetInfo()), shootState); err != nil {
return fmt.Errorf("error getting ShootState: %w", err)
diff --git a/pkg/gardenadm/botanist/system.go b/pkg/gardenadm/botanist/system.go
index 9fe160ddab7..9c337c1af51 100644
--- a/pkg/gardenadm/botanist/system.go
+++ b/pkg/gardenadm/botanist/system.go
@@ -16,12 +16,12 @@ import (
// DeployPriorityClassCritical deploys the gardener-system-critical PriorityClass needed for running
// gardener-resource-manager. This is usually deployed to seed clusters via the gardenlet helm chart. When bootstrapping
-// an autonomous shoot cluster with `gardenadm bootstrap` there is no gardenlet. Hence, we need to deploy the
+// a self-hosted shoot cluster with `gardenadm bootstrap` there is no gardenlet. Hence, we need to deploy the
// PriorityClass for gardener-resource-manager manually, as it is not taken over by the seedsystem component (it uses a
// ManagedResource for deploying the seed PriorityClasses).
// Using system-cluster-critical for gardener-resource-manager could also be good enough, but it's very simple to deploy
// the gardener-system-critical PriorityClass, so we can also choose the cleaner way.
-func (b *AutonomousBotanist) DeployPriorityClassCritical(ctx context.Context) error {
+func (b *GardenadmBotanist) DeployPriorityClassCritical(ctx context.Context) error {
priorityClass := &schedulingv1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: v1beta1constants.PriorityClassNameSeedSystemCritical}}
_, err := controllerutils.CreateOrGetAndMergePatch(ctx, b.SeedClientSet.Client(), priorityClass, func() error {
priorityClass.Value = int32(999998950)
diff --git a/pkg/gardenadm/cmd/bootstrap/bootstrap.go b/pkg/gardenadm/cmd/bootstrap/bootstrap.go
index a105338b362..be4c9aafd64 100644
--- a/pkg/gardenadm/cmd/bootstrap/bootstrap.go
+++ b/pkg/gardenadm/cmd/bootstrap/bootstrap.go
@@ -42,8 +42,8 @@ func NewCommand(globalOpts *cmd.Options) *cobra.Command {
cmd := &cobra.Command{
Use: "bootstrap",
- Short: "Bootstrap the infrastructure for an Autonomous Shoot Cluster",
- Long: "Bootstrap the infrastructure for an Autonomous Shoot Cluster (networks, machines, etc.)",
+ Short: "Bootstrap the infrastructure for a Self-Hosted Shoot Cluster",
+ Long: "Bootstrap the infrastructure for a Self-Hosted Shoot Cluster (networks, machines, etc.)",
Example: `# Bootstrap the infrastructure
gardenadm bootstrap --config-dir /path/to/manifests`,
@@ -84,7 +84,7 @@ func run(ctx context.Context, opts *Options) error {
return err
}
- b, err := botanist.NewAutonomousBotanistFromManifests(ctx, opts.Log, clientSet, opts.ConfigDir, false)
+ b, err := botanist.NewGardenadmBotanistFromManifests(ctx, opts.Log, clientSet, opts.ConfigDir, false)
if err != nil {
return err
}
@@ -222,7 +222,7 @@ func run(ctx context.Context, opts *Options) error {
})
// Scale down machine-controller-manager to prevent it from interfering with Machine objects that will be migrated
- // to the autonomous shoot. Scaling down instead of deleting it, allows operators/developers to simply scale it up
+ // to the self-hosted shoot. Scaling down instead of deleting it, allows operators/developers to simply scale it up
// again in case they need to redeploy a control plane machine manually because of errors.
scaleDownMachineControllerManager = g.Add(flow.Task{
Name: "Scaling down machine-controller-manager",
@@ -245,7 +245,7 @@ func run(ctx context.Context, opts *Options) error {
// type "Migrate". Also, this makes it easier to allow re-running `gardenadm bootstrap` in case of failures
// down the line. If we deleted the extension objects, we would need to restore them when re-running the flow.
migrateExtensionResources = g.Add(flow.Task{
- Name: "Preparing extension resources for migration to autonomous shoot",
+ Name: "Preparing extension resources for migration to self-hosted shoot",
Fn: flow.Parallel(
component.MigrateAndWait(b.Shoot.Components.Extensions.Infrastructure),
component.MigrateAndWait(b.Shoot.Components.Extensions.Worker),
@@ -327,7 +327,7 @@ func run(ctx context.Context, opts *Options) error {
fmt.Fprintf(opts.Out, `
Warning: this command is work in progress.
-For now, you can connect to the autonomous Shoot cluster control-plane by
+For now, you can connect to the self-hosted Shoot cluster control-plane by
fetching the kubeconfig from the secret "%[1]s/kubeconfig"
on the bootstrap cluster:
@@ -335,7 +335,7 @@ on the bootstrap cluster:
export KUBECONFIG=$PWD/%[1]s-kubeconfig.yaml
kubectl get nodes
-Note that the API server of the autonomous Shoot cluster control-plane might
+Note that the API server of the self-hosted Shoot cluster control-plane might
not be accessible from your current machine.
`, b.Shoot.GetInfo().Status.TechnicalID)
return nil
diff --git a/pkg/gardenadm/cmd/connect/connect.go b/pkg/gardenadm/cmd/connect/connect.go
index 0cce7513408..33af9defb1c 100644
--- a/pkg/gardenadm/cmd/connect/connect.go
+++ b/pkg/gardenadm/cmd/connect/connect.go
@@ -83,13 +83,13 @@ gardenadm connect`,
func run(ctx context.Context, opts *Options) error {
opts.Log.Info("Using resources from directory", "configDir", opts.ConfigDir)
- b, err := botanist.NewAutonomousBotanistFromManifests(ctx, opts.Log, nil, opts.ConfigDir, true)
+ b, err := botanist.NewGardenadmBotanistFromManifests(ctx, opts.Log, nil, opts.ConfigDir, true)
if err != nil {
- return fmt.Errorf("failed creating autonomous botanist: %w", err)
+ return fmt.Errorf("failed creating gardenadm botanist: %w", err)
}
b.SeedClientSet, err = b.CreateClientSet(ctx)
if err != nil {
- return fmt.Errorf("failed creating client set for autonomous shoot: %w", err)
+ return fmt.Errorf("failed creating client set for self-hosted shoot: %w", err)
}
if alreadyConnected, err := isGardenletDeployed(ctx, b); err != nil {
@@ -118,7 +118,7 @@ func run(ctx context.Context, opts *Options) error {
Dependencies: flow.NewTaskIDs(retrieveShortLivedKubeconfig),
})
deployGardenlet = g.Add(flow.Task{
- Name: "Deploying gardenlet into autonomous shoot cluster",
+ Name: "Deploying gardenlet into self-hosted shoot cluster",
Fn: func(ctx context.Context) error {
_, err := newGardenletDeployer(b, bootstrapClientSet).Reconcile(
ctx,
@@ -153,9 +153,9 @@ func run(ctx context.Context, opts *Options) error {
}
fmt.Fprintf(opts.Out, `
-Your autonomous shoot cluster has successfully been connected to Gardener!
+Your self-hosted shoot cluster has successfully been connected to Gardener!
-The gardenlet has been deployed in the %s namespace of your autonomous shoot
+The gardenlet has been deployed in the %s namespace of your self-hosted shoot
cluster and is now taking over the management and lifecycle of it. All
modifications to the Shoot specification should now be performed via the Gardener
API, rather than by directly editing resources in the cluster.
@@ -178,7 +178,7 @@ Happy Gardening!
return nil
}
-func isGardenletDeployed(ctx context.Context, b *botanist.AutonomousBotanist) (bool, error) {
+func isGardenletDeployed(ctx context.Context, b *botanist.GardenadmBotanist) (bool, error) {
if err := b.SeedClientSet.Client().Get(ctx, client.ObjectKey{Namespace: b.Shoot.ControlPlaneNamespace, Name: v1beta1constants.DeploymentNameGardenlet}, &appsv1.Deployment{}); err != nil {
if !apierrors.IsNotFound(err) {
return false, fmt.Errorf("failed checking if gardenlet deployment already exists: %w", err)
@@ -200,7 +200,7 @@ func cachedBootstrapKubeconfigPath(fs afero.Afero) string {
return filepath.Join(fs.GetTempDir(""), "gardenadm-connect-bootstrap-kubeconfig")
}
-func initializeTemporaryGardenClient(ctx context.Context, b *botanist.AutonomousBotanist, bootstrapClientSet kubernetes.Interface) error {
+func initializeTemporaryGardenClient(ctx context.Context, b *botanist.GardenadmBotanist, bootstrapClientSet kubernetes.Interface) error {
bootstrapKubeconfig, cached, err := getCachedBootstrapKubeconfig(b)
if err != nil {
return fmt.Errorf("failed retrieving cached bootstrap kubeconfig: %w", err)
@@ -220,7 +220,7 @@ func initializeTemporaryGardenClient(ctx context.Context, b *botanist.Autonomous
return setGardenClientFromKubeconfig(b, bootstrapKubeconfig)
}
-func getCachedBootstrapKubeconfig(b *botanist.AutonomousBotanist) ([]byte, bool, error) {
+func getCachedBootstrapKubeconfig(b *botanist.GardenadmBotanist) ([]byte, bool, error) {
fileInfo, err := b.FS.Stat(cachedBootstrapKubeconfigPath(b.FS))
if err != nil || time.Since(fileInfo.ModTime()) > bootstrapKubeconfigValidity-2*time.Minute {
// We deliberately ignore the error here - this is just a best-effort attempt to cache the bootstrap kubeconfig.
@@ -239,7 +239,7 @@ func getCachedBootstrapKubeconfig(b *botanist.AutonomousBotanist) ([]byte, bool,
return data, true, nil
}
-func requestShortLivedBootstrapKubeconfig(ctx context.Context, b *botanist.AutonomousBotanist, bootstrapClientSet kubernetes.Interface) ([]byte, error) {
+func requestShortLivedBootstrapKubeconfig(ctx context.Context, b *botanist.GardenadmBotanist, bootstrapClientSet kubernetes.Interface) ([]byte, error) {
certificateSubject := &pkix.Name{
Organization: []string{v1beta1constants.ShootsGroup},
CommonName: v1beta1constants.GardenadmUserNamePrefix + b.Shoot.GetInfo().Namespace + ":" + b.Shoot.GetInfo().Name,
@@ -253,7 +253,7 @@ func requestShortLivedBootstrapKubeconfig(ctx context.Context, b *botanist.Auton
return gardenletbootstraputil.CreateKubeconfigWithClientCertificate(bootstrapClientSet.RESTConfig(), privateKeyData, certData)
}
-func setGardenClientFromKubeconfig(b *botanist.AutonomousBotanist, kubeconfig []byte) error {
+func setGardenClientFromKubeconfig(b *botanist.GardenadmBotanist, kubeconfig []byte) error {
gardenClientSet, err := kubernetes.NewClientFromBytes(
kubeconfig,
kubernetes.WithClientOptions(client.Options{Scheme: kubernetes.GardenScheme}),
@@ -268,7 +268,7 @@ func setGardenClientFromKubeconfig(b *botanist.AutonomousBotanist, kubeconfig []
return nil
}
-func prepareGardenerResources(ctx context.Context, b *botanist.AutonomousBotanist) error {
+func prepareGardenerResources(ctx context.Context, b *botanist.GardenadmBotanist) error {
if err := b.GardenClient.Get(ctx, client.ObjectKeyFromObject(b.Resources.CloudProfile), &gardencorev1beta1.CloudProfile{}); err != nil {
return fmt.Errorf("failed checking for existence of CloudProfile %s (this is not created by 'gardenadm connect' and must exist in the garden cluster): %w", b.Resources.CloudProfile.Name, err)
}
@@ -290,7 +290,7 @@ func prepareGardenerResources(ctx context.Context, b *botanist.AutonomousBotanis
// We do not handle Project using 'garden' namespace because gardener-apiserver defaults .spec.tolerations for this
// Project. This requires special permissions for a custom verb that we do not want to grant to the gardenadm user
- // for autonomous shoots. Since this is a special project anyway, it must have been created beforehand.
+ // for self-hosted shoots. Since this is a special project anyway, it must have been created beforehand.
if project := b.Resources.Project.DeepCopy(); ptr.Deref(project.Spec.Namespace, "") != v1beta1constants.GardenNamespace {
if err := b.GardenClient.Create(ctx, project); client.IgnoreAlreadyExists(err) != nil {
return fmt.Errorf("failed creating Project resource %s in garden cluster: %w", project.Name, err)
@@ -334,7 +334,7 @@ func prepareGardenerResources(ctx context.Context, b *botanist.AutonomousBotanis
return nil
}
-func newGardenletDeployer(b *botanist.AutonomousBotanist, gardenClientSet kubernetes.Interface) gardenletdeployer.Interface {
+func newGardenletDeployer(b *botanist.GardenadmBotanist, gardenClientSet kubernetes.Interface) gardenletdeployer.Interface {
return &gardenletdeployer.Actuator{
GardenConfig: gardenClientSet.RESTConfig(),
GardenClient: gardenClientSet.Client(),
diff --git a/pkg/gardenadm/cmd/connect/options.go b/pkg/gardenadm/cmd/connect/options.go
index 7325e54e5ce..91d14b15b86 100644
--- a/pkg/gardenadm/cmd/connect/options.go
+++ b/pkg/gardenadm/cmd/connect/options.go
@@ -19,7 +19,7 @@ type Options struct {
*cmd.Options
cmd.ManifestOptions
- // ControlPlaneAddress is the address of the Gardener control plane to which the autonomous shoot should be connected.
+ // ControlPlaneAddress is the address of the Gardener control plane to which the self-hosted shoot should be connected.
ControlPlaneAddress string
// BootstrapToken is the bootstrap token to use for connecting the shoot.
BootstrapToken string
@@ -64,6 +64,6 @@ func (o *Options) Complete() error { return o.ManifestOptions.Complete() }
func (o *Options) addFlags(fs *pflag.FlagSet) {
o.ManifestOptions.AddFlags(fs)
fs.BytesBase64Var(&o.CertificateAuthority, "ca-certificate", nil, "Base64-encoded certificate authority bundle of the Gardener control plane")
- fs.StringVar(&o.BootstrapToken, "bootstrap-token", "", "Bootstrap token for connecting the autonomous shoot cluster to a garden cluster (create it with 'gardenadm token' in the garden cluster)")
+ fs.StringVar(&o.BootstrapToken, "bootstrap-token", "", "Bootstrap token for connecting the self-hosted shoot cluster to a garden cluster (create it with 'gardenadm token' in the garden cluster)")
fs.BoolVar(&o.Force, "force", false, "Forces the deployment of gardenlet, even if it already exists")
}
diff --git a/pkg/gardenadm/cmd/init/init.go b/pkg/gardenadm/cmd/init/init.go
index 37083e4ccdb..fb5950fb03f 100644
--- a/pkg/gardenadm/cmd/init/init.go
+++ b/pkg/gardenadm/cmd/init/init.go
@@ -337,7 +337,7 @@ cluster.
Note that the mentioned kubeconfig file will be disabled once you deploy the
gardenlet and connect this cluster to an existing Gardener installation. Run
this while targeting the garden cluster to which you want to connect this
-autonomous shoot cluster:
+self-hosted shoot cluster:
gardenadm token create --print-connect-command --shoot-namespace=%s --shoot-name=%s
@@ -351,8 +351,8 @@ see https://gardener.cloud/docs/gardener/shoot/shoot_access/.
return nil
}
-func bootstrapControlPlane(ctx context.Context, opts *Options) (*botanist.AutonomousBotanist, error) {
- b, err := botanist.NewAutonomousBotanistFromManifests(ctx, opts.Log, nil, opts.ConfigDir, true)
+func bootstrapControlPlane(ctx context.Context, opts *Options) (*botanist.GardenadmBotanist, error) {
+ b, err := botanist.NewGardenadmBotanistFromManifests(ctx, opts.Log, nil, opts.ConfigDir, true)
if err != nil {
return nil, err
}
@@ -417,5 +417,5 @@ func bootstrapControlPlane(ctx context.Context, opts *Options) (*botanist.Autono
return nil, flow.Errors(err)
}
- return botanist.NewAutonomousBotanistFromManifests(ctx, opts.Log, clientSet, opts.ConfigDir, true)
+ return botanist.NewGardenadmBotanistFromManifests(ctx, opts.Log, clientSet, opts.ConfigDir, true)
}
diff --git a/pkg/gardenadm/cmd/join/join.go b/pkg/gardenadm/cmd/join/join.go
index 31e8781aa3b..369304b3e8b 100644
--- a/pkg/gardenadm/cmd/join/join.go
+++ b/pkg/gardenadm/cmd/join/join.go
@@ -25,7 +25,7 @@ func NewCommand(globalOpts *cmd.Options) *cobra.Command {
Short: "Bootstrap worker nodes and join them to the cluster",
Long: `Bootstrap worker nodes and join them to the cluster.
-This command helps to initialize and configure a node to join an existing autonomous shoot cluster.
+This command helps to initialize and configure a node to join an existing self-hosted shoot cluster.
It ensures that the necessary configurations are applied and the node is properly registered as a worker or control plane node.
Note that further control plane nodes cannot be joined currently.`,
@@ -57,9 +57,9 @@ gardenadm join --bootstrap-token --ca-certificate --gardener-n
}
func run(ctx context.Context, opts *Options) error {
- b, err := botanist.NewAutonomousBotanistWithoutResources(opts.Log)
+ b, err := botanist.NewGardenadmBotanistWithoutResources(opts.Log)
if err != nil {
- return fmt.Errorf("failed creating autonomous botanist: %w", err)
+ return fmt.Errorf("failed creating gardenadm botanist: %w", err)
}
version, err := b.DiscoverKubernetesVersion(opts.ControlPlaneAddress, opts.CertificateAuthority, opts.BootstrapToken)
diff --git a/pkg/gardenadm/cmd/token/create/options.go b/pkg/gardenadm/cmd/token/create/options.go
index 62af1517b0f..1b54a087abc 100644
--- a/pkg/gardenadm/cmd/token/create/options.go
+++ b/pkg/gardenadm/cmd/token/create/options.go
@@ -31,7 +31,7 @@ type Options struct {
// 'worker'.
WorkerPoolName string
// Shoot contains the namespace and the name of the Shoot which should be connected to Gardener. This is only
- // relevant for bootstrap tokens that are used for connecting autonomous shoots via `gardenadm connect`.
+ // relevant for bootstrap tokens that are used for connecting self-hosted shoots via `gardenadm connect`.
Shoot types.NamespacedName
// PrintJoinCommand specifies whether to print the full `gardenadm join` command.
@@ -114,9 +114,9 @@ func (o *Options) Complete() error {
o.Token.ID, o.Token.Secret = split[0], split[1]
if o.Shoot.Namespace != "" && o.Shoot.Name != "" {
- o.Description = fmt.Sprintf("%s%s to Gardener via 'gardenadm connect'", bootstraptoken.AutonomousShootBootstrapTokenSecretDescriptionPrefix, o.Shoot.String())
+ o.Description = fmt.Sprintf("%s%s to Gardener via 'gardenadm connect'", bootstraptoken.SelfHostedShootBootstrapTokenSecretDescriptionPrefix, o.Shoot.String())
} else if len(o.Description) == 0 {
- o.Description = "Used for joining nodes to an autonomous shoot cluster via 'gardenadm join'"
+ o.Description = "Used for joining nodes to a self-hosted shoot cluster via 'gardenadm join'"
}
return nil
diff --git a/pkg/gardenadm/cmd/token/create/options_test.go b/pkg/gardenadm/cmd/token/create/options_test.go
index e07fb156b0d..7ae1cbacdaa 100644
--- a/pkg/gardenadm/cmd/token/create/options_test.go
+++ b/pkg/gardenadm/cmd/token/create/options_test.go
@@ -125,14 +125,14 @@ var _ = Describe("Options", func() {
options.Shoot.Namespace = "bar"
Expect(options.Complete()).To(Succeed())
- Expect(options.Description).To(Equal("Used for connecting the autonomous Shoot bar/foo to Gardener via 'gardenadm connect'"))
+ Expect(options.Description).To(Equal("Used for connecting the self-hosted Shoot bar/foo to Gardener via 'gardenadm connect'"))
})
It("should default the description for 'gardenadm join' when no shoot info is provided", func() {
options.Token.Combined = "foo.bar"
Expect(options.Complete()).To(Succeed())
- Expect(options.Description).To(Equal("Used for joining nodes to an autonomous shoot cluster via 'gardenadm join'"))
+ Expect(options.Description).To(Equal("Used for joining nodes to a self-hosted shoot cluster via 'gardenadm join'"))
})
})
})
diff --git a/pkg/gardenadm/cmd/token/generate/generate.go b/pkg/gardenadm/cmd/token/generate/generate.go
index 89539ae8b39..dfe5e5759ea 100644
--- a/pkg/gardenadm/cmd/token/generate/generate.go
+++ b/pkg/gardenadm/cmd/token/generate/generate.go
@@ -23,7 +23,7 @@ func NewCommand(globalOpts *cmd.Options) *cobra.Command {
cmd := &cobra.Command{
Use: "generate",
Short: "Generate a random bootstrap token for joining a node",
- Long: `Generate a random bootstrap token that can be used for joining a node to an autonomous shoot cluster.
+ Long: `Generate a random bootstrap token that can be used for joining a node to a self-hosted shoot cluster.
Note that the token is not created on the server (use 'gardenadm token create' for it).
The token is securely generated and follows the format "[a-z0-9]{6}.[a-z0-9]{16}".
Read more about it here: https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/`,
diff --git a/pkg/gardenadm/cmd/token/utils/clientset.go b/pkg/gardenadm/cmd/token/utils/clientset.go
index 323a2ef145d..9a244a5df94 100644
--- a/pkg/gardenadm/cmd/token/utils/clientset.go
+++ b/pkg/gardenadm/cmd/token/utils/clientset.go
@@ -15,8 +15,8 @@ import (
botanistpkg "github.com/gardener/gardener/pkg/gardenlet/operation/botanist"
)
-// CreateClientSet creates a new client set using the AutonomousBotanist to create the client set.
+// CreateClientSet creates a new client set using the GardenadmBotanist to create the client set.
// Exposed for unit testing.
var CreateClientSet = func(ctx context.Context, log logr.Logger) (kubernetes.Interface, error) {
- return (&botanist.AutonomousBotanist{Botanist: &botanistpkg.Botanist{Operation: &operation.Operation{Logger: log}}}).CreateClientSet(ctx)
+ return (&botanist.GardenadmBotanist{Botanist: &botanistpkg.Botanist{Operation: &operation.Operation{Logger: log}}}).CreateClientSet(ctx)
}
diff --git a/pkg/gardenlet/bootstrap/bootstrap.go b/pkg/gardenlet/bootstrap/bootstrap.go
index e5a15b3ee06..1e06b83cfff 100644
--- a/pkg/gardenlet/bootstrap/bootstrap.go
+++ b/pkg/gardenlet/bootstrap/bootstrap.go
@@ -33,7 +33,7 @@ import (
const (
// SeedCSRPrefix defines the prefix of seed CSR created by gardenlet.
SeedCSRPrefix = "seed-csr-"
- // ShootCSRPrefix defines the prefix of autonomous shoot CSR created by gardenlet.
+ // ShootCSRPrefix defines the prefix of self-hosted shoot CSR created by gardenlet.
ShootCSRPrefix = "shoot-csr-"
)
@@ -46,7 +46,7 @@ func RequestKubeconfigWithBootstrapClient(
bootstrapClientSet kubernetes.Interface,
kubeconfigKey, bootstrapKubeconfigKey client.ObjectKey,
seedConfig *gardenletconfigv1alpha1.SeedConfig,
- autonomousShootMeta *types.NamespacedName,
+ selfHostedShootMeta *types.NamespacedName,
validityDuration *metav1.Duration,
) (
[]byte,
@@ -69,17 +69,17 @@ func RequestKubeconfigWithBootstrapClient(
CommonName: v1beta1constants.SeedUserNamePrefix + seedName,
}
- case gardenlet.IsResponsibleForAutonomousShoot():
- log = log.WithValues("shoot", autonomousShootMeta)
+ case gardenlet.IsResponsibleForSelfHostedShoot():
+ log = log.WithValues("shoot", selfHostedShootMeta)
csrPrefix = ShootCSRPrefix
certificateSubject = &pkix.Name{
Organization: []string{v1beta1constants.ShootsGroup},
- CommonName: v1beta1constants.ShootUserNamePrefix + autonomousShootMeta.Namespace + ":" + autonomousShootMeta.Name,
+ CommonName: v1beta1constants.ShootUserNamePrefix + selfHostedShootMeta.Namespace + ":" + selfHostedShootMeta.Name,
}
default:
- return nil, "", fmt.Errorf("failed determining gardenlet bootstrap scenario (seed or autonomous shoot)")
+ return nil, "", fmt.Errorf("failed determining gardenlet bootstrap scenario (seed or self-hosted shoot)")
}
certData, privateKeyData, csrName, err := certificatesigningrequest.RequestCertificate(ctx, log, bootstrapClientSet.Kubernetes(), certificateSubject, []string{}, []net.IP{}, validityDuration, csrPrefix)
diff --git a/pkg/gardenlet/bootstrap/bootstrap_test.go b/pkg/gardenlet/bootstrap/bootstrap_test.go
index a8bb0982db2..f80ebb9e916 100644
--- a/pkg/gardenlet/bootstrap/bootstrap_test.go
+++ b/pkg/gardenlet/bootstrap/bootstrap_test.go
@@ -74,7 +74,7 @@ var _ = Describe("Bootstrap", func() {
gardenClientConnection *gardenletconfigv1alpha1.GardenClientConnection
kubeconfigKey client.ObjectKey
bootstrapKubeconfigKey client.ObjectKey
- autonomousShootMeta *types.NamespacedName
+ selfHostedShootMeta *types.NamespacedName
approvedCSR = certificatesv1.CertificateSigningRequest{
ObjectMeta: metav1.ObjectMeta{
@@ -194,7 +194,7 @@ var _ = Describe("Bootstrap", func() {
},
})
- kubeconfig, csrName, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, seedConfig, autonomousShootMeta, nil)
+ kubeconfig, csrName, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, seedConfig, selfHostedShootMeta, nil)
Expect(err).NotTo(HaveOccurred())
Expect(kubeconfig).ToNot(BeEmpty())
@@ -215,7 +215,7 @@ var _ = Describe("Bootstrap", func() {
WithKubernetes(kubeClient).
Build()
- _, _, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, seedConfig, autonomousShootMeta, nil)
+ _, _, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, seedConfig, selfHostedShootMeta, nil)
Expect(err).To(MatchError(ContainSubstring("is denied")))
})
@@ -233,7 +233,7 @@ var _ = Describe("Bootstrap", func() {
WithKubernetes(kubeClient).
Build()
- _, _, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, seedConfig, autonomousShootMeta, nil)
+ _, _, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, seedConfig, selfHostedShootMeta, nil)
Expect(err).To(MatchError(ContainSubstring("failed")))
})
})
@@ -243,7 +243,7 @@ var _ = Describe("Bootstrap", func() {
Expect(os.Setenv("NAMESPACE", "kube-system")).To(Succeed())
DeferCleanup(func() { Expect(os.Setenv("NAMESPACE", "")).To(Succeed()) })
- autonomousShootMeta = &types.NamespacedName{Namespace: "shoot-namespace", Name: "shoot-name"}
+ selfHostedShootMeta = &types.NamespacedName{Namespace: "shoot-namespace", Name: "shoot-name"}
})
It("should not return an error", func() {
@@ -277,7 +277,7 @@ var _ = Describe("Bootstrap", func() {
},
})
- kubeconfig, csrName, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, nil, autonomousShootMeta, nil)
+ kubeconfig, csrName, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, nil, selfHostedShootMeta, nil)
Expect(err).NotTo(HaveOccurred())
Expect(kubeconfig).ToNot(BeEmpty())
@@ -298,7 +298,7 @@ var _ = Describe("Bootstrap", func() {
WithKubernetes(kubeClient).
Build()
- _, _, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, nil, autonomousShootMeta, nil)
+ _, _, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, nil, selfHostedShootMeta, nil)
Expect(err).To(MatchError(ContainSubstring("is denied")))
})
@@ -316,7 +316,7 @@ var _ = Describe("Bootstrap", func() {
WithKubernetes(kubeClient).
Build()
- _, _, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, nil, autonomousShootMeta, nil)
+ _, _, err := RequestKubeconfigWithBootstrapClient(ctx, testLogger, runtimeClient, bootstrapClientSet, kubeconfigKey, bootstrapKubeconfigKey, nil, selfHostedShootMeta, nil)
Expect(err).To(MatchError(ContainSubstring("failed")))
})
})
diff --git a/pkg/gardenlet/bootstrap/certificate/certificate_rotation.go b/pkg/gardenlet/bootstrap/certificate/certificate_rotation.go
index 71d11cb20c7..bd2e25749bd 100644
--- a/pkg/gardenlet/bootstrap/certificate/certificate_rotation.go
+++ b/pkg/gardenlet/bootstrap/certificate/certificate_rotation.go
@@ -56,7 +56,7 @@ func NewCertificateManager(
gardenCluster cluster.Cluster,
seedClient client.Client,
config *gardenletconfigv1alpha1.GardenletConfiguration,
- autonomousShootMeta *types.NamespacedName,
+ selfHostedShootMeta *types.NamespacedName,
) (
*Manager,
error,
@@ -72,8 +72,8 @@ func NewCertificateManager(
}
logger := log.WithName("certificate-manager")
- if autonomousShootMeta != nil {
- logger = logger.WithValues("shootNamespace", autonomousShootMeta.Namespace, "shootName", autonomousShootMeta.Name)
+ if selfHostedShootMeta != nil {
+ logger = logger.WithValues("shootNamespace", selfHostedShootMeta.Namespace, "shootName", selfHostedShootMeta.Name)
} else {
logger = logger.WithValues("seedName", gardenletbootstraputil.GetSeedName(config.SeedConfig))
}
@@ -84,8 +84,8 @@ func NewCertificateManager(
seedClient: seedClient,
gardenClientConnection: config.GardenClientConnection,
newTargetedObject: func() client.Object {
- if autonomousShootMeta != nil {
- return &gardencorev1beta1.Shoot{ObjectMeta: metav1.ObjectMeta{Namespace: autonomousShootMeta.Namespace, Name: autonomousShootMeta.Name}}
+ if selfHostedShootMeta != nil {
+ return &gardencorev1beta1.Shoot{ObjectMeta: metav1.ObjectMeta{Namespace: selfHostedShootMeta.Namespace, Name: selfHostedShootMeta.Name}}
}
return &gardencorev1beta1.Seed{ObjectMeta: metav1.ObjectMeta{Name: gardenletbootstraputil.GetSeedName(config.SeedConfig)}}
},
@@ -130,7 +130,7 @@ func (cr *Manager) ScheduleCertificateRotation(ctx context.Context, gardenletCan
return nil
}
-// getTargetedObject returns the Seed or the autonomous Shoot that this Gardenlet is reconciling.
+// getTargetedObject returns the Seed or the self-hosted Shoot that this Gardenlet is reconciling.
func (cr *Manager) getTargetedObject(ctx context.Context) (client.Object, error) {
obj := cr.newTargetedObject()
if err := cr.gardenClientSet.Client().Get(ctx, client.ObjectKeyFromObject(obj), obj); err != nil {
diff --git a/pkg/gardenlet/bootstrappers/garden_kubeconfig.go b/pkg/gardenlet/bootstrappers/garden_kubeconfig.go
index 5c9b86d3018..ffaaf2f2eb5 100644
--- a/pkg/gardenlet/bootstrappers/garden_kubeconfig.go
+++ b/pkg/gardenlet/bootstrappers/garden_kubeconfig.go
@@ -22,15 +22,15 @@ import (
// GardenKubeconfig implements manager.Runnable and can be used to fetch a kubeconfig for the garden cluster.
type GardenKubeconfig struct {
- // RuntimeClient is the runtime cluster client (seed or autonomous shoot).
+ // RuntimeClient is the runtime cluster client (seed or self-hosted shoot).
RuntimeClient client.Client
// Log is a logger.
Log logr.Logger
// Config is the gardenlet component configuration.
Config *gardenletconfigv1alpha1.GardenletConfiguration
- // AutonomousShootMeta is the NamespacedName of the autonomous shoot the gardenlet is responsible for (if
+ // SelfHostedShootMeta is the NamespacedName of the self-hosted shoot the gardenlet is responsible for (if
// applicable).
- AutonomousShootMeta *types.NamespacedName
+ SelfHostedShootMeta *types.NamespacedName
// Result is a structure that will be filled with information about the requested kubeconfig. Must be initialized
// by the caller.
Result *KubeconfigBootstrapResult
@@ -147,7 +147,7 @@ func (g *GardenKubeconfig) getOrBootstrapKubeconfig(ctx context.Context) ([]byte
kubeconfigKey,
bootstrapKubeconfigKey,
g.Config.SeedConfig,
- g.AutonomousShootMeta,
+ g.SelfHostedShootMeta,
g.Config.GardenClientConnection.KubeconfigValidity.Validity,
)
}
diff --git a/pkg/gardenlet/controller/add.go b/pkg/gardenlet/controller/add.go
index bd2b4c3a496..be3da54bb35 100644
--- a/pkg/gardenlet/controller/add.go
+++ b/pkg/gardenlet/controller/add.go
@@ -57,7 +57,7 @@ func AddToManager(
// adapt the shoot authorizer (via the resource dependency graph) to allow 'read' access to this ConfigMap (similar
// to how it's done for seeds).
gardenClusterIdentity := ""
- if !gardenletutils.IsResponsibleForAutonomousShoot() {
+ if !gardenletutils.IsResponsibleForSelfHostedShoot() {
configMap := &corev1.ConfigMap{}
if err := gardenCluster.GetClient().Get(ctx, client.ObjectKey{Namespace: metav1.NamespaceSystem, Name: v1beta1constants.ClusterIdentity}, configMap); err != nil {
return fmt.Errorf("failed getting cluster-identity ConfigMap in garden cluster: %w", err)
@@ -79,8 +79,8 @@ func AddToManager(
return fmt.Errorf("failed creating seed clientset: %w", err)
}
- if gardenletutils.IsResponsibleForAutonomousShoot() {
- mgr.GetLogger().Info("Running in autonomous shoot, registering minimal set of controllers")
+ if gardenletutils.IsResponsibleForSelfHostedShoot() {
+ mgr.GetLogger().Info("Running in self-hosted shoot, registering minimal set of controllers")
if err := (&gardenlet.Reconciler{
Config: *cfg,
diff --git a/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/reconciler.go b/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/reconciler.go
index 064e471d7b8..10ff0d4886e 100644
--- a/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/reconciler.go
+++ b/pkg/gardenlet/controller/controllerinstallation/controllerinstallation/reconciler.go
@@ -62,7 +62,7 @@ const usablePortsRangeSize = 5
// the process of being deleted when deleting a ControllerInstallation.
var RequeueDurationWhenResourceDeletionStillPresent = 5 * time.Second
-// Reconciler reconciles ControllerInstallations and deploys them into the seed cluster or the autonomous shoot cluster.
+// Reconciler reconciles ControllerInstallations and deploys them into the seed cluster or the self-hosted shoot cluster.
type Reconciler struct {
GardenClient client.Client
GardenConfig *rest.Config
@@ -80,7 +80,7 @@ type Reconciler struct {
BootstrapControlPlaneNode bool
}
-// Reconcile reconciles ControllerInstallations and deploys them into the seed cluster or the autonomous shoot cluster.
+// Reconcile reconciles ControllerInstallations and deploys them into the seed cluster or the self-hosted shoot cluster.
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
@@ -262,8 +262,8 @@ func (r *Reconciler) reconcile(
},
}
- if metav1.HasLabel(seed.ObjectMeta, v1beta1constants.LabelAutonomousShootCluster) {
- gardenerValues["gardener"].(map[string]any)["autonomousShootCluster"] = true
+ if metav1.HasLabel(seed.ObjectMeta, v1beta1constants.LabelSelfHostedShootCluster) {
+ gardenerValues["gardener"].(map[string]any)["selfHostedShootCluster"] = true
}
if genericGardenKubeconfigSecretName != "" {
@@ -582,7 +582,7 @@ func objectEnablesGardenKubeconfig(o runtime.Object) bool {
}
// MutateSpecForControlPlaneNodeBootstrapping adapts host network, replicas, tolerations and usable ports range for
-// autonomous shoot clusters if necessary.
+// self-hosted shoot clusters if necessary.
func (r *Reconciler) MutateSpecForControlPlaneNodeBootstrapping(obj runtime.Object) error {
if !r.BootstrapControlPlaneNode {
return nil
diff --git a/pkg/gardenlet/controller/gardenlet/add.go b/pkg/gardenlet/controller/gardenlet/add.go
index dc787185490..b25450af351 100644
--- a/pkg/gardenlet/controller/gardenlet/add.go
+++ b/pkg/gardenlet/controller/gardenlet/add.go
@@ -50,7 +50,7 @@ func (r *Reconciler) AddToManager(
r.Clock = clock.RealClock{}
}
if r.GardenNamespace == "" {
- if gardenlet.IsResponsibleForAutonomousShoot() {
+ if gardenlet.IsResponsibleForSelfHostedShoot() {
r.GardenNamespace = metav1.NamespaceSystem
} else {
r.GardenNamespace = v1beta1constants.GardenNamespace
diff --git a/pkg/gardenlet/controller/gardenlet/reconciler.go b/pkg/gardenlet/controller/gardenlet/reconciler.go
index 80deacb694f..095f741e230 100644
--- a/pkg/gardenlet/controller/gardenlet/reconciler.go
+++ b/pkg/gardenlet/controller/gardenlet/reconciler.go
@@ -74,7 +74,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
}
var seed *gardencorev1beta1.Seed
- if !strings.HasPrefix(gardenlet.Name, gardenletutils.ResourcePrefixAutonomousShoot) {
+ if !strings.HasPrefix(gardenlet.Name, gardenletutils.ResourcePrefixSelfHostedShoot) {
seed, err = gardenletdeployer.GetSeed(ctx, r.GardenClient, gardenlet.Name)
if err != nil {
r.Recorder.Eventf(gardenlet, corev1.EventTypeWarning, gardencorev1beta1.EventReconcileError, err.Error())
diff --git a/pkg/gardenlet/operation/botanist/machinecontrollermanager.go b/pkg/gardenlet/operation/botanist/machinecontrollermanager.go
index cf6074531ad..6a6d3f82c7a 100644
--- a/pkg/gardenlet/operation/botanist/machinecontrollermanager.go
+++ b/pkg/gardenlet/operation/botanist/machinecontrollermanager.go
@@ -31,7 +31,7 @@ func (b *Botanist) DefaultMachineControllerManager() (machinecontrollermanager.I
b.SecretsManager,
machinecontrollermanager.Values{
Image: image.String(),
- AutonomousShoot: b.Shoot.IsAutonomous(),
+ SelfHostedShoot: b.Shoot.IsSelfHosted(),
},
), nil
}
diff --git a/pkg/gardenlet/operation/botanist/resource_manager.go b/pkg/gardenlet/operation/botanist/resource_manager.go
index 7521df47f16..05e4ca7a5aa 100644
--- a/pkg/gardenlet/operation/botanist/resource_manager.go
+++ b/pkg/gardenlet/operation/botanist/resource_manager.go
@@ -58,7 +58,7 @@ func (b *Botanist) DefaultResourceManager() (resourcemanager.Interface, error) {
}
)
- if b.Shoot.IsAutonomous() {
+ if b.Shoot.IsSelfHosted() {
values.KubernetesServiceHost = nil
if b.Shoot.RunsControlPlane() {
diff --git a/pkg/gardenlet/operation/botanist/secrets.go b/pkg/gardenlet/operation/botanist/secrets.go
index 925fa53702d..0f9ef1045da 100644
--- a/pkg/gardenlet/operation/botanist/secrets.go
+++ b/pkg/gardenlet/operation/botanist/secrets.go
@@ -74,7 +74,7 @@ func (b *Botanist) lastSecretRotationStartTimes() map[string]time.Time {
if shootStatus := b.Shoot.GetInfo().Status; shootStatus.Credentials != nil && shootStatus.Credentials.Rotation != nil {
if shootStatus.Credentials.Rotation.CertificateAuthorities != nil && shootStatus.Credentials.Rotation.CertificateAuthorities.LastInitiationTime != nil {
- for _, config := range caCertConfigurations(b.Shoot.IsWorkerless, b.Shoot.IsAutonomous()) {
+ for _, config := range caCertConfigurations(b.Shoot.IsWorkerless, b.Shoot.IsSelfHosted()) {
rotation[config.GetName()] = shootStatus.Credentials.Rotation.CertificateAuthorities.LastInitiationTime.Time
}
// The static token secret contains token for the health check of the kube-apiserver.
@@ -148,7 +148,7 @@ func (b *Botanist) restoreSecretsFromShootState(ctx context.Context) error {
return flow.Parallel(fns...)(ctx)
}
-func caCertConfigurations(isWorkerless, isAutonomous bool) []secretsutils.ConfigInterface {
+func caCertConfigurations(isWorkerless, isSelfHosted bool) []secretsutils.ConfigInterface {
certificateSecretConfigs := []secretsutils.ConfigInterface{
// The CommonNames for CA certificates will be overridden with the secret name by the secrets manager when
// generated to ensure that each CA has a unique common name. For backwards-compatibility, we still keep the
@@ -167,7 +167,7 @@ func caCertConfigurations(isWorkerless, isAutonomous bool) []secretsutils.Config
&secretsutils.CertificateSecretConfig{Name: v1beta1constants.SecretNameCAMetricsServer, CommonName: "metrics-server", CertType: secretsutils.CACert},
)
- if !isAutonomous {
+ if !isSelfHosted {
certificateSecretConfigs = append(certificateSecretConfigs,
&secretsutils.CertificateSecretConfig{Name: v1beta1constants.SecretNameCAVPN, CommonName: "vpn", CertType: secretsutils.CACert},
)
@@ -209,7 +209,7 @@ func (b *Botanist) caCertGenerateOptionsFor(configName string) []secretsmanager.
func (b *Botanist) generateCertificateAuthorities(ctx context.Context) error {
var caClientSecret *corev1.Secret
- for _, config := range caCertConfigurations(b.Shoot.IsWorkerless, b.Shoot.IsAutonomous()) {
+ for _, config := range caCertConfigurations(b.Shoot.IsWorkerless, b.Shoot.IsSelfHosted()) {
caSecret, err := b.SecretsManager.Generate(ctx, config, b.caCertGenerateOptionsFor(config.GetName())...)
if err != nil {
return err
diff --git a/pkg/gardenlet/operation/botanist/worker.go b/pkg/gardenlet/operation/botanist/worker.go
index 9e22cc3b6fd..2b3302233a4 100644
--- a/pkg/gardenlet/operation/botanist/worker.go
+++ b/pkg/gardenlet/operation/botanist/worker.go
@@ -30,8 +30,8 @@ import (
func (b *Botanist) DefaultWorker() worker.Interface {
workers := b.Shoot.GetInfo().Spec.Provider.Workers
// In `gardenadm bootstrap` we only deploy the control plane worker pool. When running `gardenadm init` on the
- // medium-touch control plane, the full `Worker` with all pools will be deployed.
- if b.Shoot.IsAutonomous() && !b.Shoot.RunsControlPlane() {
+ // created control plane nodes, the full `Worker` with all pools will be deployed.
+ if b.Shoot.IsSelfHosted() && !b.Shoot.RunsControlPlane() {
workers = []gardencorev1beta1.Worker{*v1beta1helper.ControlPlaneWorkerPoolForShoot(b.Shoot.GetInfo().DeepCopy().Spec.Provider.Workers)}
}
diff --git a/pkg/gardenlet/operation/shoot/shoot.go b/pkg/gardenlet/operation/shoot/shoot.go
index a6e7379d620..1be74c87d84 100644
--- a/pkg/gardenlet/operation/shoot/shoot.go
+++ b/pkg/gardenlet/operation/shoot/shoot.go
@@ -663,20 +663,19 @@ func copyUniqueCIDRs(src []string, dst []net.IPNet, networkType string) ([]net.I
return dst, nil
}
-// IsAutonomous returns true in case of an autonomous shoot cluster.
-func (s *Shoot) IsAutonomous() bool {
- return v1beta1helper.IsShootAutonomous(s.GetInfo().Spec.Provider.Workers)
+// IsSelfHosted returns true in case of a self-hosted shoot cluster.
+func (s *Shoot) IsSelfHosted() bool {
+ return v1beta1helper.IsShootSelfHosted(s.GetInfo().Spec.Provider.Workers)
}
// RunsControlPlane returns true in case the Kubernetes control plane runs inside the cluster.
-// In contrast to IsAutonomous, this function returns false when bootstrapping autonomous shoot clusters using
-// `gardenadm bootstrap` (medium-touch scenario).
+// In contrast to IsSelfHosted, this function returns false when bootstrapping self-hosted shoot clusters using
+// `gardenadm bootstrap` ("managed infrastructure" scenario).
func (s *Shoot) RunsControlPlane() bool {
return s.ControlPlaneNamespace == metav1.NamespaceSystem
}
// HasManagedInfrastructure returns true if the shoot's infrastructure (network, machines, etc.) is managed by Gardener.
-// I.e., it returns false for high-touch autonomous shoots, where the infrastructure is managed by the user.
func (s *Shoot) HasManagedInfrastructure() bool {
return v1beta1helper.HasManagedInfrastructure(s.GetInfo())
}
diff --git a/pkg/gardenlet/operation/shoot/shoot_test.go b/pkg/gardenlet/operation/shoot/shoot_test.go
index 6086bbf100e..0410186f018 100644
--- a/pkg/gardenlet/operation/shoot/shoot_test.go
+++ b/pkg/gardenlet/operation/shoot/shoot_test.go
@@ -191,7 +191,7 @@ var _ = Describe("shoot", func() {
})
Describe("#ComputeInClusterAPIServerAddress", func() {
- When("shoot is not autonomous", func() {
+ When("shoot is not self-hosted", func() {
controlPlaneNamespace := "foo"
s := &Shoot{ControlPlaneNamespace: controlPlaneNamespace}
@@ -204,7 +204,7 @@ var _ = Describe("shoot", func() {
})
})
- When("shoot is autonomous", func() {
+ When("shoot is self-hosted", func() {
s := &Shoot{ControlPlaneNamespace: "kube-system"}
It("should return kubernetes.default.svc", func() {
@@ -265,7 +265,7 @@ var _ = Describe("shoot", func() {
})
})
- Describe("#IsAutonomous", func() {
+ Describe("#IsSelfHosted", func() {
It("should return true", func() {
shoot.SetInfo(&gardencorev1beta1.Shoot{
Spec: gardencorev1beta1.ShootSpec{
@@ -277,7 +277,7 @@ var _ = Describe("shoot", func() {
},
},
})
- Expect(shoot.IsAutonomous()).To(BeTrue())
+ Expect(shoot.IsSelfHosted()).To(BeTrue())
})
It("should return false", func() {
@@ -290,7 +290,7 @@ var _ = Describe("shoot", func() {
},
},
})
- Expect(shoot.IsAutonomous()).To(BeFalse())
+ Expect(shoot.IsSelfHosted()).To(BeFalse())
})
})
diff --git a/pkg/gardenlet/operation/shoot/types.go b/pkg/gardenlet/operation/shoot/types.go
index 8bc7c39e490..1853e15202c 100644
--- a/pkg/gardenlet/operation/shoot/types.go
+++ b/pkg/gardenlet/operation/shoot/types.go
@@ -79,7 +79,7 @@ type Shoot struct {
ControlPlaneNamespace string
KubernetesVersion *semver.Version
- // InternalClusterDomain is empty for autonomous shoots, which only have an external domain (Shoot.spec.dns.domain).
+ // InternalClusterDomain is empty for self-hosted shoots, which only have an external domain (Shoot.spec.dns.domain).
InternalClusterDomain *string
// ExternalClusterDomain is nil if Shoot.Spec.DNS.Domain is unset.
ExternalClusterDomain *string
diff --git a/pkg/operator/controller/garden/garden/components.go b/pkg/operator/controller/garden/garden/components.go
index 7aa5cee5806..605870a8363 100644
--- a/pkg/operator/controller/garden/garden/components.go
+++ b/pkg/operator/controller/garden/garden/components.go
@@ -718,7 +718,7 @@ func (r *Reconciler) newKubeAPIServer(
),
newAuthorizationWebhook("shoot", kubeconfigShootAuthz,
// only intercept request from shoot gardenlets
- // TODO(rfranzke): Also handle requests from ServiceAccounts of extensions running in the autonomous shoot.
+ // TODO(rfranzke): Also handle requests from ServiceAccounts of extensions running in the self-hosted shoot.
fmt.Sprintf("'%s' in request.groups", v1beta1constants.ShootsGroup),
),
)
diff --git a/pkg/operator/controller/gardenlet/add.go b/pkg/operator/controller/gardenlet/add.go
index c03be1c5c20..6e5d97af564 100644
--- a/pkg/operator/controller/gardenlet/add.go
+++ b/pkg/operator/controller/gardenlet/add.go
@@ -88,7 +88,7 @@ func (r *Reconciler) OperatorResponsiblePredicate(ctx context.Context) predicate
if !ok {
return false
}
- return !strings.HasPrefix(gardenlet.Name, gardenletutils.ResourcePrefixAutonomousShoot) &&
+ return !strings.HasPrefix(gardenlet.Name, gardenletutils.ResourcePrefixSelfHostedShoot) &&
(hasForceRedeployOperationAnnotation(gardenlet) ||
r.seedDoesNotExist(ctx, gardenlet) ||
gardenlet.Spec.KubeconfigSecretRef != nil)
diff --git a/pkg/operator/controller/gardenlet/add_test.go b/pkg/operator/controller/gardenlet/add_test.go
index d5c6cda1159..b69934f3078 100644
--- a/pkg/operator/controller/gardenlet/add_test.go
+++ b/pkg/operator/controller/gardenlet/add_test.go
@@ -50,8 +50,8 @@ var _ = Describe("Add", func() {
test(gardenlet, BeTrue())
})
- It("should return false because gardenlet name is prefixed with 'autonomous-shoot'", func() {
- gardenlet.Name = "autonomous-shoot-" + gardenlet.Name
+ It("should return false because gardenlet name is prefixed with 'self-hosted-shoot'", func() {
+ gardenlet.Name = "self-hosted-shoot-" + gardenlet.Name
test(gardenlet, BeFalse())
})
diff --git a/pkg/provider-local/controller/dnsrecord/actuator.go b/pkg/provider-local/controller/dnsrecord/actuator.go
index 55ad746b3d5..905d40f3207 100644
--- a/pkg/provider-local/controller/dnsrecord/actuator.go
+++ b/pkg/provider-local/controller/dnsrecord/actuator.go
@@ -69,10 +69,10 @@ func (a *Actuator) ForceDelete(ctx context.Context, log logr.Logger, dnsRecord *
return a.Delete(ctx, log, dnsRecord, cluster)
}
-// Migrate removes the DNS record from the CoreDNS config map if the shoot is not autonomous.
+// Migrate removes the DNS record from the CoreDNS config map if the shoot is not self-hosted.
func (a *Actuator) Migrate(ctx context.Context, log logr.Logger, dnsRecord *extensionsv1alpha1.DNSRecord, cluster *extensionscontroller.Cluster) error {
- if v1beta1helper.IsShootAutonomous(cluster.Shoot.Spec.Provider.Workers) {
- // Do nothing when migrating DNSRecord of autonomous shoot with managed infrastructure. The CoreDNS
+ if v1beta1helper.IsShootSelfHosted(cluster.Shoot.Spec.Provider.Workers) {
+ // Do nothing when migrating DNSRecord of self-hosted shoot with managed infrastructure. The CoreDNS
// rewrite rules are still needed for the control plane machines to resolve the kube-apiserver domain.
return nil
}
@@ -99,7 +99,7 @@ func keyForDNSRecord(dnsRecord *extensionsv1alpha1.DNSRecord) string {
}
func (a *Actuator) configForDNSRecord(ctx context.Context, dnsRecord *extensionsv1alpha1.DNSRecord, cluster *extensionscontroller.Cluster) (string, error) {
- if v1beta1helper.IsShootAutonomous(cluster.Shoot.Spec.Provider.Workers) {
+ if v1beta1helper.IsShootSelfHosted(cluster.Shoot.Spec.Provider.Workers) {
switch dnsRecord.Spec.RecordType {
case extensionsv1alpha1.DNSRecordTypeA, extensionsv1alpha1.DNSRecordTypeAAAA:
// We need to use the `template` plugin because the `hosts` plugin can only be used once per server block.
@@ -112,7 +112,7 @@ func (a *Actuator) configForDNSRecord(ctx context.Context, dnsRecord *extensions
return config, nil
default:
- return "", fmt.Errorf("unsupported record type %q for autonomous shoot, only A and AAAA are supported", dnsRecord.Spec.RecordType)
+ return "", fmt.Errorf("unsupported record type %q for self-hosted shoot, only A and AAAA are supported", dnsRecord.Spec.RecordType)
}
}
diff --git a/pkg/provider-local/controller/dnsrecord/actuator_test.go b/pkg/provider-local/controller/dnsrecord/actuator_test.go
index ac3c94d4ba3..fb6edac999f 100644
--- a/pkg/provider-local/controller/dnsrecord/actuator_test.go
+++ b/pkg/provider-local/controller/dnsrecord/actuator_test.go
@@ -199,7 +199,7 @@ var _ = Describe("Actuator", func() {
})
})
- Context("autonomous shoots", func() {
+ Context("self-hosted shoots", func() {
BeforeEach(func() {
cluster.Shoot.Spec.Provider.Workers = []gardencorev1beta1.Worker{{
ControlPlane: &gardencorev1beta1.WorkerControlPlane{},
@@ -246,7 +246,7 @@ var _ = Describe("Actuator", func() {
apiDNSRecord.Spec.RecordType = "CNAME"
apiDNSRecord.Spec.Values = []string{"some.other.name.gardener.cloud"}
- Expect(actuator.Reconcile(ctx, log, apiDNSRecord, cluster)).To(MatchError(ContainSubstring(`unsupported record type "CNAME" for autonomous shoot`)))
+ Expect(actuator.Reconcile(ctx, log, apiDNSRecord, cluster)).To(MatchError(ContainSubstring(`unsupported record type "CNAME" for self-hosted shoot`)))
})
})
diff --git a/pkg/provider-local/controller/worker/add.go b/pkg/provider-local/controller/worker/add.go
index a660681de23..9f81604a59d 100644
--- a/pkg/provider-local/controller/worker/add.go
+++ b/pkg/provider-local/controller/worker/add.go
@@ -33,8 +33,8 @@ type AddOptions struct {
IgnoreOperationAnnotation bool
// ExtensionClass defines the extension class this extension is responsible for.
ExtensionClass extensionsv1alpha1.ExtensionClass
- // AutonomousShootCluster indicates whether the extension runs in an autonomous shoot cluster.
- AutonomousShootCluster bool
+ // SelfHostedShootCluster indicates whether the extension runs in a self-hosted shoot cluster.
+ SelfHostedShootCluster bool
}
// AddToManagerWithOptions adds a controller with the given Options to the given manager.
@@ -54,7 +54,7 @@ func AddToManagerWithOptions(ctx context.Context, mgr manager.Manager, opts AddO
Predicates: worker.DefaultPredicates(ctx, mgr, opts.IgnoreOperationAnnotation),
Type: local.Type,
ExtensionClass: opts.ExtensionClass,
- AutonomousShootCluster: opts.AutonomousShootCluster,
+ SelfHostedShootCluster: opts.SelfHostedShootCluster,
})
}
diff --git a/pkg/provider-local/webhook/dnsconfig/add.go b/pkg/provider-local/webhook/dnsconfig/add.go
index 76f0f4f920a..70abd371a59 100644
--- a/pkg/provider-local/webhook/dnsconfig/add.go
+++ b/pkg/provider-local/webhook/dnsconfig/add.go
@@ -59,9 +59,9 @@ func AddToManagerWithOptions(mgr manager.Manager, _ AddOptions) (*extensionswebh
Target: extensionswebhook.TargetSeed,
Path: name,
Webhook: &admission.Webhook{Handler: handler, RecoverPanic: ptr.To(true)},
- // This webhook should not act on the local setup for the gardenadm high-touch scenario.
+ // This webhook should not act on the local setup for the gardenadm "unmanaged infrastructure" scenario.
NamespaceSelector: &metav1.LabelSelector{MatchExpressions: []metav1.LabelSelectorRequirement{
- {Key: corev1.LabelMetadataName, Operator: metav1.LabelSelectorOpNotIn, Values: []string{"gardenadm-high-touch"}},
+ {Key: corev1.LabelMetadataName, Operator: metav1.LabelSelectorOpNotIn, Values: []string{"gardenadm-unmanaged-infra"}},
}},
ObjectSelector: &metav1.LabelSelector{MatchExpressions: []metav1.LabelSelectorRequirement{
{Key: "app", Operator: metav1.LabelSelectorOpIn, Values: []string{
diff --git a/pkg/scheduler/controller/shoot/add.go b/pkg/scheduler/controller/shoot/add.go
index 39e17b64d4c..f8e039e2bb8 100644
--- a/pkg/scheduler/controller/shoot/add.go
+++ b/pkg/scheduler/controller/shoot/add.go
@@ -42,7 +42,7 @@ func (r *Reconciler) AddToManager(mgr manager.Manager) error {
For(&gardencorev1beta1.Shoot{}, builder.WithPredicates(
r.ShootUnassignedPredicate(),
r.ShootSpecChangedPredicate(),
- r.ShootIsNotAutonomous(),
+ r.ShootIsNotSelfHosted(),
predicate.Not(predicateutils.IsDeleting()),
)).
WithOptions(controller.Options{
@@ -82,12 +82,12 @@ func (r *Reconciler) ShootSpecChangedPredicate() predicate.Predicate {
}
}
-// ShootIsNotAutonomous is a predicate that returns true if a shoot is not mark as 'autonomous shoot cluster' (meaning,
+// ShootIsNotSelfHosted is a predicate that returns true if a shoot is not mark as 'self-hosted shoot cluster' (meaning,
// that the control plane components run in the same cluster, hence, no seed selection is required).
-func (r *Reconciler) ShootIsNotAutonomous() predicate.Predicate {
+func (r *Reconciler) ShootIsNotSelfHosted() predicate.Predicate {
return predicate.NewPredicateFuncs(func(obj client.Object) bool {
if shoot, ok := obj.(*gardencorev1beta1.Shoot); ok {
- return !helper.IsShootAutonomous(shoot.Spec.Provider.Workers)
+ return !helper.IsShootSelfHosted(shoot.Spec.Provider.Workers)
}
return false
})
diff --git a/pkg/scheduler/controller/shoot/add_test.go b/pkg/scheduler/controller/shoot/add_test.go
index 7421db4da54..75c1f97727f 100644
--- a/pkg/scheduler/controller/shoot/add_test.go
+++ b/pkg/scheduler/controller/shoot/add_test.go
@@ -158,7 +158,7 @@ var _ = Describe("Add", func() {
})
})
- Describe("#ShootIsNotAutonomous", func() {
+ Describe("#ShootIsNotSelfHosted", func() {
var (
predicate predicate.Predicate
shoot *gardencorev1beta1.Shoot
@@ -170,7 +170,7 @@ var _ = Describe("Add", func() {
)
BeforeEach(func() {
- predicate = reconciler.ShootIsNotAutonomous()
+ predicate = reconciler.ShootIsNotSelfHosted()
shoot = &gardencorev1beta1.Shoot{}
createEvent = event.CreateEvent{Object: shoot}
@@ -179,7 +179,7 @@ var _ = Describe("Add", func() {
genericEvent = event.GenericEvent{Object: shoot}
})
- Context("shoot is autonomous", func() {
+ Context("shoot is self-hosted", func() {
It("should be false", func() {
shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, gardencorev1beta1.Worker{ControlPlane: &gardencorev1beta1.WorkerControlPlane{}})
Expect(predicate.Create(createEvent)).To(BeFalse())
@@ -189,7 +189,7 @@ var _ = Describe("Add", func() {
})
})
- Context("shoot is not autonomous", func() {
+ Context("shoot is not self-hosted", func() {
It("should be true", func() {
Expect(predicate.Create(createEvent)).To(BeTrue())
Expect(predicate.Update(updateEvent)).To(BeTrue())
diff --git a/pkg/utils/gardener/csr.go b/pkg/utils/gardener/csr.go
index 15d01dccb57..f20d0e592c9 100644
--- a/pkg/utils/gardener/csr.go
+++ b/pkg/utils/gardener/csr.go
@@ -39,20 +39,20 @@ func IsSeedClientCert(x509cr *x509.CertificateRequest, usages []certificatesv1.K
}
// IsGardenadmClientCert returns true when the given CSR and usages match the requirements for a client
-// certificate for an autonomous shoot with the `gardenadm connect` prefix. If false is returned, a reason will be
+// certificate for a self-hosted shoot with the `gardenadm connect` prefix. If false is returned, a reason will be
// returned explaining which requirement was not met.
func IsGardenadmClientCert(x509cr *x509.CertificateRequest, usages []certificatesv1.KeyUsage) (bool, string) {
- return isAutonomousShootClientCert(x509cr, usages, v1beta1constants.GardenadmUserNamePrefix)
+ return isSelfHostedShootClientCert(x509cr, usages, v1beta1constants.GardenadmUserNamePrefix)
}
// IsShootClientCert returns true when the given CSR and usages match the requirements for a client certificate for an
-// autonomous shoot with the gardenlet prefix. If false is returned, a reason will be returned explaining which
+// self-hosted shoot with the gardenlet prefix. If false is returned, a reason will be returned explaining which
// requirement was not met.
func IsShootClientCert(x509cr *x509.CertificateRequest, usages []certificatesv1.KeyUsage) (bool, string) {
- return isAutonomousShootClientCert(x509cr, usages, v1beta1constants.ShootUserNamePrefix)
+ return isSelfHostedShootClientCert(x509cr, usages, v1beta1constants.ShootUserNamePrefix)
}
-func isAutonomousShootClientCert(x509cr *x509.CertificateRequest, usages []certificatesv1.KeyUsage, prefix string) (bool, string) {
+func isSelfHostedShootClientCert(x509cr *x509.CertificateRequest, usages []certificatesv1.KeyUsage, prefix string) (bool, string) {
requiredOrganizations := []string{v1beta1constants.ShootsGroup}
if !reflect.DeepEqual(requiredOrganizations, x509cr.Subject.Organization) {
diff --git a/pkg/utils/gardener/gardenlet/gardenlet.go b/pkg/utils/gardener/gardenlet/gardenlet.go
index 39bfeb9d39d..ee8b5724534 100644
--- a/pkg/utils/gardener/gardenlet/gardenlet.go
+++ b/pkg/utils/gardener/gardenlet/gardenlet.go
@@ -67,12 +67,12 @@ func SetDefaultGardenClusterAddress(log logr.Logger, gardenletConfigRaw runtime.
return *newGardenletConfigRaw, nil
}
-// ResourcePrefixAutonomousShoot is the prefix for resources related to Gardenlet created for autonomous shoots.
-const ResourcePrefixAutonomousShoot = "autonomous-shoot-"
+// ResourcePrefixSelfHostedShoot is the prefix for resources related to Gardenlet created for self-hosted shoots.
+const ResourcePrefixSelfHostedShoot = "self-hosted-shoot-"
-// IsResponsibleForAutonomousShoot checks if the current process is responsible for managing autonomous shoots. This is
+// IsResponsibleForSelfHostedShoot checks if the current process is responsible for managing self-hosted shoots. This is
// determined by checking if the environment variable "NAMESPACE" is set to the kube-system namespace.
-func IsResponsibleForAutonomousShoot() bool {
+func IsResponsibleForSelfHostedShoot() bool {
return os.Getenv("NAMESPACE") == metav1.NamespaceSystem
}
@@ -90,11 +90,11 @@ func ShootMetaFromBootstrapToken(ctx context.Context, reader client.Reader, boot
func extractShootMetaFromBootstrapToken(bootstrapTokenSecret *corev1.Secret) (types.NamespacedName, error) {
description := string(bootstrapTokenSecret.Data[bootstraptokenapi.BootstrapTokenDescriptionKey])
- if !strings.HasPrefix(description, bootstraptoken.AutonomousShootBootstrapTokenSecretDescriptionPrefix) {
- return types.NamespacedName{}, fmt.Errorf("bootstrap token description does not start with %q: %s", bootstraptoken.AutonomousShootBootstrapTokenSecretDescriptionPrefix, description)
+ if !strings.HasPrefix(description, bootstraptoken.SelfHostedShootBootstrapTokenSecretDescriptionPrefix) {
+ return types.NamespacedName{}, fmt.Errorf("bootstrap token description does not start with %q: %s", bootstraptoken.SelfHostedShootBootstrapTokenSecretDescriptionPrefix, description)
}
- parts := strings.Fields(strings.TrimPrefix(description, bootstraptoken.AutonomousShootBootstrapTokenSecretDescriptionPrefix))
+ parts := strings.Fields(strings.TrimPrefix(description, bootstraptoken.SelfHostedShootBootstrapTokenSecretDescriptionPrefix))
if len(parts) == 0 {
return types.NamespacedName{}, fmt.Errorf("could not extract shoot meta from bootstrap token description: %s", description)
}
diff --git a/pkg/utils/gardener/gardenlet/gardenlet_test.go b/pkg/utils/gardener/gardenlet/gardenlet_test.go
index 1a943b013cf..f1bcafbc671 100644
--- a/pkg/utils/gardener/gardenlet/gardenlet_test.go
+++ b/pkg/utils/gardener/gardenlet/gardenlet_test.go
@@ -124,16 +124,16 @@ var _ = Describe("Gardenlet", func() {
})
})
- Describe("#IsResponsibleForAutonomousShoot", func() {
+ Describe("#IsResponsibleForSelfHostedShoot", func() {
It("should return true because the NAMESPACE environment variable is set to 'kube-system'", func() {
Expect(os.Setenv("NAMESPACE", "kube-system")).To(Succeed())
DeferCleanup(func() { Expect(os.Setenv("NAMESPACE", "")).To(Succeed()) })
- Expect(IsResponsibleForAutonomousShoot()).To(BeTrue())
+ Expect(IsResponsibleForSelfHostedShoot()).To(BeTrue())
})
It("should return false because the NAMESPACE environment variable is not set to 'kube-system'", func() {
- Expect(IsResponsibleForAutonomousShoot()).To(BeFalse())
+ Expect(IsResponsibleForSelfHostedShoot()).To(BeFalse())
})
})
@@ -167,7 +167,7 @@ var _ = Describe("Gardenlet", func() {
Namespace: "kube-system",
},
Data: map[string][]byte{
- "description": []byte("Used for connecting the autonomous Shoot " + expectedShootNamespace + "/" + expectedShootName + " to Gardener via 'gardenadm connect'"),
+ "description": []byte("Used for connecting the self-hosted Shoot " + expectedShootNamespace + "/" + expectedShootName + " to Gardener via 'gardenadm connect'"),
},
}
@@ -211,7 +211,7 @@ var _ = Describe("Gardenlet", func() {
Namespace: "kube-system",
},
Data: map[string][]byte{
- "description": []byte("Used for connecting the autonomous Shoot "),
+ "description": []byte("Used for connecting the self-hosted Shoot "),
},
}
@@ -230,7 +230,7 @@ var _ = Describe("Gardenlet", func() {
Namespace: "kube-system",
},
Data: map[string][]byte{
- "description": []byte("Used for connecting the autonomous Shoot "),
+ "description": []byte("Used for connecting the self-hosted Shoot "),
},
}
@@ -249,7 +249,7 @@ var _ = Describe("Gardenlet", func() {
Namespace: "kube-system",
},
Data: map[string][]byte{
- "description": []byte("Used for connecting the autonomous Shoot invalid-format-no-slash"),
+ "description": []byte("Used for connecting the self-hosted Shoot invalid-format-no-slash"),
},
}
@@ -268,7 +268,7 @@ var _ = Describe("Gardenlet", func() {
Namespace: "kube-system",
},
Data: map[string][]byte{
- "description": []byte("Used for connecting the autonomous Shoot namespace/shoot/extra"),
+ "description": []byte("Used for connecting the self-hosted Shoot namespace/shoot/extra"),
},
}
@@ -287,7 +287,7 @@ var _ = Describe("Gardenlet", func() {
Namespace: "kube-system",
},
Data: map[string][]byte{
- "description": []byte("Used for connecting the autonomous Shoot /my-shoot"),
+ "description": []byte("Used for connecting the self-hosted Shoot /my-shoot"),
},
}
@@ -305,7 +305,7 @@ var _ = Describe("Gardenlet", func() {
Namespace: "kube-system",
},
Data: map[string][]byte{
- "description": []byte("Used for connecting the autonomous Shoot my-namespace/"),
+ "description": []byte("Used for connecting the self-hosted Shoot my-namespace/"),
},
}
@@ -323,7 +323,7 @@ var _ = Describe("Gardenlet", func() {
Namespace: "kube-system",
},
Data: map[string][]byte{
- "description": []byte("Used for connecting the autonomous Shoot " + expectedShootNamespace + "/" + expectedShootName + " additional text here"),
+ "description": []byte("Used for connecting the self-hosted Shoot " + expectedShootNamespace + "/" + expectedShootName + " additional text here"),
},
}
diff --git a/pkg/utils/gardener/shoot.go b/pkg/utils/gardener/shoot.go
index 76f33c8efa4..9ef5d5e9e6b 100644
--- a/pkg/utils/gardener/shoot.go
+++ b/pkg/utils/gardener/shoot.go
@@ -622,9 +622,9 @@ func ConstructExternalDomain(ctx context.Context, c client.Reader, shoot *garden
)
switch {
- case v1beta1helper.IsShootAutonomous(shoot.Spec.Provider.Workers) && !v1beta1helper.HasManagedInfrastructure(shoot):
- // For high-touch autonomous shoots, the external domain is managed outside of Gardener, but must be specified
- // in the Shoot resource. Therefore, we do not have to set any secret/zone data here.
+ case v1beta1helper.IsShootSelfHosted(shoot.Spec.Provider.Workers) && !v1beta1helper.HasManagedInfrastructure(shoot):
+ // For self-hosted shoots w/o managed infrastructure, the external domain is managed outside of Gardener, but
+ // must be specified in the Shoot resource. Therefore, we do not have to set any secret/zone data here.
// When removing the "unmanaged provider" (https://github.com/gardener/gardener/issues/12212), replace this value
// with a bool field on the Domain type that is considered by the NeedsExternalDNS func.
externalDomain.Provider = core.DNSUnmanaged
diff --git a/pkg/utils/gardener/shoot_test.go b/pkg/utils/gardener/shoot_test.go
index 653702965ce..929dfbf3b82 100644
--- a/pkg/utils/gardener/shoot_test.go
+++ b/pkg/utils/gardener/shoot_test.go
@@ -1070,7 +1070,7 @@ var _ = Describe("Shoot", func() {
Expect(err).NotTo(HaveOccurred())
})
- It("returns the unmanaged external domain for autonomous shoots", func(ctx SpecContext) {
+ It("returns the unmanaged external domain for self-hosted shoots", func(ctx SpecContext) {
shoot := &gardencorev1beta1.Shoot{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
@@ -1446,7 +1446,7 @@ var _ = Describe("Shoot", func() {
)))
})
- It("should compute the correct list of required extensions (autonomous shoot with backup)", func() {
+ It("should compute the correct list of required extensions (self-hosted shoot with backup)", func() {
shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, gardencorev1beta1.Worker{
ControlPlane: &gardencorev1beta1.WorkerControlPlane{Backup: &gardencorev1beta1.Backup{Provider: backupProvider}},
})
diff --git a/pkg/utils/graph/eventhandler_gardenlet.go b/pkg/utils/graph/eventhandler_gardenlet.go
index 917df4d2a11..987f761199d 100644
--- a/pkg/utils/graph/eventhandler_gardenlet.go
+++ b/pkg/utils/graph/eventhandler_gardenlet.go
@@ -64,7 +64,7 @@ func (g *graph) handleGardenletCreateOrUpdate(ctx context.Context, gardenlet *se
g.lock.Lock()
defer g.lock.Unlock()
- if g.forAutonomousShoots {
+ if g.forSelfHostedShoots {
g.handleGardenletCreateOrUpdateForShoots(gardenlet)
} else {
g.handleGardenletCreateOrUpdateForSeeds(ctx, gardenlet)
@@ -83,7 +83,7 @@ func (g *graph) handleGardenletDelete(name, namespace string) {
}
func (g *graph) handleGardenletCreateOrUpdateForSeeds(ctx context.Context, gardenlet *seedmanagementv1alpha1.Gardenlet) {
- if strings.HasPrefix(gardenlet.Name, gardenletutils.ResourcePrefixAutonomousShoot) {
+ if strings.HasPrefix(gardenlet.Name, gardenletutils.ResourcePrefixSelfHostedShoot) {
return
}
@@ -141,7 +141,7 @@ func (g *graph) handleGardenletCreateOrUpdateForSeeds(ctx context.Context, garde
}
func (g *graph) handleGardenletCreateOrUpdateForShoots(gardenlet *seedmanagementv1alpha1.Gardenlet) {
- if !strings.HasPrefix(gardenlet.Name, gardenletutils.ResourcePrefixAutonomousShoot) {
+ if !strings.HasPrefix(gardenlet.Name, gardenletutils.ResourcePrefixSelfHostedShoot) {
return
}
@@ -150,11 +150,11 @@ func (g *graph) handleGardenletCreateOrUpdateForShoots(gardenlet *seedmanagement
var (
gardenletVertex = g.getOrCreateVertex(VertexTypeGardenlet, gardenlet.Namespace, gardenlet.Name)
- shootVertex = g.getOrCreateVertex(VertexTypeShoot, gardenlet.Namespace, strings.TrimPrefix(gardenlet.Name, gardenletutils.ResourcePrefixAutonomousShoot))
+ shootVertex = g.getOrCreateVertex(VertexTypeShoot, gardenlet.Namespace, strings.TrimPrefix(gardenlet.Name, gardenletutils.ResourcePrefixSelfHostedShoot))
)
g.addEdge(gardenletVertex, shootVertex)
- // TODO(rfranzke): Check if we need to support the 'allowBootstrap' logic for autonomous shoots as well (see
+ // TODO(rfranzke): Check if we need to support the 'allowBootstrap' logic for self-hosted shoots as well (see
// handling for seeds).
}
diff --git a/pkg/utils/graph/eventhandler_shoot.go b/pkg/utils/graph/eventhandler_shoot.go
index 175a66d1df2..a102356bb84 100644
--- a/pkg/utils/graph/eventhandler_shoot.go
+++ b/pkg/utils/graph/eventhandler_shoot.go
@@ -106,7 +106,7 @@ func (g *graph) HandleShootCreateOrUpdate(ctx context.Context, shoot *gardencore
g.deleteAllIncomingEdges(VertexTypeSecretBinding, VertexTypeShoot, shoot.Namespace, shoot.Name)
g.deleteAllIncomingEdges(VertexTypeCredentialsBinding, VertexTypeShoot, shoot.Namespace, shoot.Name)
g.deleteAllIncomingEdges(VertexTypeShootState, VertexTypeShoot, shoot.Namespace, shoot.Name)
- if !g.forAutonomousShoots {
+ if !g.forSelfHostedShoots {
g.deleteAllOutgoingEdges(VertexTypeShoot, shoot.Namespace, shoot.Name, VertexTypeSeed)
}
diff --git a/pkg/utils/graph/graph.go b/pkg/utils/graph/graph.go
index 78bf566139f..4f33d7ee26c 100644
--- a/pkg/utils/graph/graph.go
+++ b/pkg/utils/graph/graph.go
@@ -45,19 +45,19 @@ type graph struct {
client client.Client
graph *simple.DirectedGraph
vertices typeVertexMapping
- forAutonomousShoots bool
+ forSelfHostedShoots bool
}
var _ Interface = &graph{}
// New creates a new graph interface for tracking resource dependencies.
-func New(logger logr.Logger, client client.Client, forAutonomousShoots bool) *graph {
+func New(logger logr.Logger, client client.Client, forSelfHostedShoots bool) *graph {
return &graph{
logger: logger,
client: client,
graph: simple.NewDirectedGraph(),
vertices: make(typeVertexMapping),
- forAutonomousShoots: forAutonomousShoots,
+ forSelfHostedShoots: forSelfHostedShoots,
}
}
@@ -69,7 +69,7 @@ type resourceSetup struct {
func (g *graph) Setup(ctx context.Context, c cache.Cache) error {
var setups []resourceSetup
- if g.forAutonomousShoots {
+ if g.forSelfHostedShoots {
setups = append(setups,
resourceSetup{&certificatesv1.CertificateSigningRequest{}, g.setupCertificateSigningRequestWatch},
resourceSetup{&seedmanagementv1alpha1.Gardenlet{}, g.setupGardenletWatch},
diff --git a/pkg/utils/graph/graph_test.go b/pkg/utils/graph/graph_test.go
index 59d04ba0795..3a928c11416 100644
--- a/pkg/utils/graph/graph_test.go
+++ b/pkg/utils/graph/graph_test.go
@@ -2580,7 +2580,7 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
}
gardenlet1 = &seedmanagementv1alpha1.Gardenlet{
- ObjectMeta: metav1.ObjectMeta{Name: "autonomous-shoot-" + shootName, Namespace: shootNamespace},
+ ObjectMeta: metav1.ObjectMeta{Name: "self-hosted-shoot-" + shootName, Namespace: shootNamespace},
}
namespace1 = &corev1.Namespace{
diff --git a/pkg/utils/kubernetes/bootstraptoken/bootstraptoken.go b/pkg/utils/kubernetes/bootstraptoken/bootstraptoken.go
index 367d7b90c03..273496860b6 100644
--- a/pkg/utils/kubernetes/bootstraptoken/bootstraptoken.go
+++ b/pkg/utils/kubernetes/bootstraptoken/bootstraptoken.go
@@ -98,6 +98,6 @@ func TokenID(meta metav1.ObjectMeta) string {
return utils.ComputeSHA256Hex([]byte(value))[:IDLength]
}
-// AutonomousShootBootstrapTokenSecretDescriptionPrefix is the prefix used in the description of a bootstrap token
-// secret for autonomous shoots. It indicates that the token is used for connecting the autonomous Shoot to Gardener.
-const AutonomousShootBootstrapTokenSecretDescriptionPrefix = "Used for connecting the autonomous Shoot "
+// SelfHostedShootBootstrapTokenSecretDescriptionPrefix is the prefix used in the description of a bootstrap token
+// secret for self-hosted shoots. It indicates that the token is used for connecting the self-hosted Shoot to Gardener.
+const SelfHostedShootBootstrapTokenSecretDescriptionPrefix = "Used for connecting the self-hosted Shoot "
diff --git a/plugin/pkg/global/customverbauthorizer/admission.go b/plugin/pkg/global/customverbauthorizer/admission.go
index f1fe12d255b..13325f63aa2 100644
--- a/plugin/pkg/global/customverbauthorizer/admission.go
+++ b/plugin/pkg/global/customverbauthorizer/admission.go
@@ -52,9 +52,9 @@ const (
// `.spec.limits` limits in `NamespacedCloudProfile` resources above values defined in the parent `CloudProfile`.
CustomVerbNamespacedCloudProfileRaiseLimits = "raise-spec-limits"
- // CustomVerbShootMarkAutonomous is a constant for the custom verb that allows setting the
- // `.spec.provider.workers[].controlPlane` field in the `Shoot` spec which marks it as 'autonomous shoot cluster'.
- CustomVerbShootMarkAutonomous = "mark-autonomous"
+ // CustomVerbShootMarkSelfHosted is a constant for the custom verb that allows setting the
+ // `.spec.provider.workers[].controlPlane` field in the `Shoot` spec which marks it as 'self-hosted shoot cluster'.
+ CustomVerbShootMarkSelfHosted = "mark-self-hosted"
)
// Register registers a plugin.
@@ -257,7 +257,7 @@ func (c *CustomVerbAuthorizer) admitShoots(ctx context.Context, a admission.Attr
}
if mustCheckShootAutonomy(oldObj, obj) {
- return c.authorize(ctx, a, CustomVerbShootMarkAutonomous, "modify .spec.provider.workers[].controlPlane")
+ return c.authorize(ctx, a, CustomVerbShootMarkSelfHosted, "modify .spec.provider.workers[].controlPlane")
}
return nil
diff --git a/plugin/pkg/global/customverbauthorizer/admission_test.go b/plugin/pkg/global/customverbauthorizer/admission_test.go
index f32ff2dab18..b298f189dfc 100644
--- a/plugin/pkg/global/customverbauthorizer/admission_test.go
+++ b/plugin/pkg/global/customverbauthorizer/admission_test.go
@@ -857,9 +857,9 @@ var _ = Describe("customverbauthorizer", func() {
Expect(err).NotTo(HaveOccurred())
})
- Context("mark autonomous", func() {
+ Context("mark self-hosted", func() {
BeforeEach(func() {
- authorizeAttributes.Verb = "mark-autonomous"
+ authorizeAttributes.Verb = "mark-self-hosted"
})
It("should always allow creating a shoot without whitelist tolerations", func() {
@@ -872,14 +872,14 @@ var _ = Describe("customverbauthorizer", func() {
auth.EXPECT().Authorize(ctx, authorizeAttributes).Return(authorizer.DecisionAllow, "", nil)
})
- It("should allow creating an autonomous shoot", func() {
+ It("should allow creating a self-hosted shoot", func() {
shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, core.Worker{ControlPlane: &core.WorkerControlPlane{}})
attrs = admission.NewAttributesRecord(shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
})
- It("should allow marking an existing shoot as 'autonomous'", func() {
+ It("should allow marking an existing shoot as 'self-hosted'", func() {
// NB: This is already forbidden by validation, but this admission plugin does not know about it, so let's test it for completeness.
shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, core.Worker{})
oldShoot := shoot.DeepCopy()
@@ -889,7 +889,7 @@ var _ = Describe("customverbauthorizer", func() {
Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
})
- It("should allow removing the control plane field of autonomous shoots", func() {
+ It("should allow removing the control plane field of self-hosted shoots", func() {
// NB: This is already forbidden by validation, but this admission plugin does not know about it, so let's test it for completeness.
shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, core.Worker{ControlPlane: &core.WorkerControlPlane{}})
oldShoot := shoot.DeepCopy()
@@ -905,14 +905,14 @@ var _ = Describe("customverbauthorizer", func() {
auth.EXPECT().Authorize(ctx, authorizeAttributes).Return(authorizer.DecisionDeny, "", nil)
})
- It("should forbid creating an autonomous shoot", func() {
+ It("should forbid creating a self-hosted shoot", func() {
shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, core.Worker{ControlPlane: &core.WorkerControlPlane{}})
attrs = admission.NewAttributesRecord(shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
Expect(admissionHandler.Validate(ctx, attrs, nil)).NotTo(Succeed())
})
- It("should allow removing the control plane field of autonomous shoots", func() {
+ It("should allow removing the control plane field of self-hosted shoots", func() {
// NB: This is already forbidden by validation, but this admission plugin does not know about it, so let's test it for completeness.
shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, core.Worker{ControlPlane: &core.WorkerControlPlane{}})
oldShoot := shoot.DeepCopy()
diff --git a/skaffold-gardenadm.yaml b/skaffold-gardenadm.yaml
index d40b35d15b9..63fecc64b89 100644
--- a/skaffold-gardenadm.yaml
+++ b/skaffold-gardenadm.yaml
@@ -997,7 +997,7 @@ build:
- bash
- -c
- >
- kubectl --kubeconfig="$VIRTUAL_GARDEN_KUBECONFIG" -n garden patch gardenlet autonomous-shoot-root --type=merge -p "{\"spec\":{\"deployment\":{\"helm\":{\"ociRepository\":{\"ref\":\"$SKAFFOLD_IMAGE\"}}}}}" || true
+ kubectl --kubeconfig="$VIRTUAL_GARDEN_KUBECONFIG" -n garden patch gardenlet self-hosted-shoot-root --type=merge -p "{\"spec\":{\"deployment\":{\"helm\":{\"ociRepository\":{\"ref\":\"$SKAFFOLD_IMAGE\"}}}}}" || true
insecureRegistries:
- garden.local.gardener.cloud:5001
@@ -1277,16 +1277,16 @@ resourceSelector:
image:
- .*
profiles:
- - name: high-touch
+ - name: unmanaged-infra
manifests:
kustomize:
paths:
- - dev-setup/gardenadm/resources/overlays/high-touch
- - name: medium-touch
+ - dev-setup/gardenadm/resources/overlays/unmanaged-infra
+ - name: managed-infra
manifests:
kustomize:
paths:
- - dev-setup/gardenadm/resources/overlays/medium-touch
+ - dev-setup/gardenadm/resources/overlays/managed-infra
---
apiVersion: skaffold/v4beta12
kind: Config
@@ -1315,7 +1315,7 @@ deploy:
kubectl -n "$SKAFFOLD_NAMESPACES" cp dev-setup/gardenadm/resources/generated/.skaffold-image "$pod:/tmp/.skaffold-image"
kubectl -n "$SKAFFOLD_NAMESPACES" cp dev-setup/gardenadm/resources/generated/.imagevector-overwrite.yaml "$pod:/gardenadm/imagevector-overwrite.yaml"
kubectl -n "$SKAFFOLD_NAMESPACES" cp dev-setup/gardenadm/resources/generated/.imagevector-overwrite-charts.yaml "$pod:/gardenadm/imagevector-overwrite-charts.yaml"
- kubectl -n "$SKAFFOLD_NAMESPACES" cp dev-setup/gardenadm/resources/generated/high-touch/manifests.yaml "$pod:/gardenadm/resources/manifests.yaml"
+ kubectl -n "$SKAFFOLD_NAMESPACES" cp dev-setup/gardenadm/resources/generated/unmanaged-infra/manifests.yaml "$pod:/gardenadm/resources/manifests.yaml"
done
- container:
command:
diff --git a/test/e2e/gardenadm/e2e_suite_test.go b/test/e2e/gardenadm/e2e_suite_test.go
index a5aac4e91c0..0909fb5e27c 100644
--- a/test/e2e/gardenadm/e2e_suite_test.go
+++ b/test/e2e/gardenadm/e2e_suite_test.go
@@ -14,8 +14,8 @@ import (
"github.com/gardener/gardener/pkg/logger"
. "github.com/gardener/gardener/test/e2e/gardenadm/common"
- _ "github.com/gardener/gardener/test/e2e/gardenadm/hightouch"
- _ "github.com/gardener/gardener/test/e2e/gardenadm/mediumtouch"
+ _ "github.com/gardener/gardener/test/e2e/gardenadm/managedinfra"
+ _ "github.com/gardener/gardener/test/e2e/gardenadm/unmanagedinfra"
)
func TestE2E(t *testing.T) {
diff --git a/test/e2e/gardenadm/mediumtouch/exec.go b/test/e2e/gardenadm/managedinfra/exec.go
similarity index 99%
rename from test/e2e/gardenadm/mediumtouch/exec.go
rename to test/e2e/gardenadm/managedinfra/exec.go
index fb098ff7409..a4b5dea74ae 100644
--- a/test/e2e/gardenadm/mediumtouch/exec.go
+++ b/test/e2e/gardenadm/managedinfra/exec.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
-package mediumtouch
+package managedinfra
import (
"context"
diff --git a/test/e2e/gardenadm/mediumtouch/gardenadm.go b/test/e2e/gardenadm/managedinfra/gardenadm.go
similarity index 97%
rename from test/e2e/gardenadm/mediumtouch/gardenadm.go
rename to test/e2e/gardenadm/managedinfra/gardenadm.go
index 8f834ea87bf..bc216288ec4 100644
--- a/test/e2e/gardenadm/mediumtouch/gardenadm.go
+++ b/test/e2e/gardenadm/managedinfra/gardenadm.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
-package mediumtouch
+package managedinfra
import (
"context"
@@ -35,7 +35,7 @@ import (
shootmigration "github.com/gardener/gardener/test/utils/shoots/migration"
)
-var _ = Describe("gardenadm medium-touch scenario tests", Label("gardenadm", "medium-touch"), func() {
+var _ = Describe("gardenadm managed infrastructure scenario tests", Label("gardenadm", "managed-infra"), func() {
BeforeEach(OncePerOrdered, func(SpecContext) {
PrepareBinary()
}, NodeTimeout(5*time.Minute))
@@ -72,7 +72,7 @@ var _ = Describe("gardenadm medium-touch scenario tests", Label("gardenadm", "me
It("should start the bootstrap flow", func() {
// Start the gardenadm process but don't wait for it to complete so that we can asynchronously perform assertions
// on individual steps in the test specs below.
- session = Run("bootstrap", "-d", "../../../dev-setup/gardenadm/resources/generated/medium-touch", "--kubeconfig-output", kubeconfigOutputFile)
+ session = Run("bootstrap", "-d", "../../../dev-setup/gardenadm/resources/generated/managed-infra", "--kubeconfig-output", kubeconfigOutputFile)
})
It("should auto-detect the system's public IPs", func(ctx SpecContext) {
@@ -186,7 +186,7 @@ var _ = Describe("gardenadm medium-touch scenario tests", Label("gardenadm", "me
}, SpecTimeout(15*time.Minute))
It("should write the shoot kubeconfig to the specified file", func(ctx SpecContext) {
- Eventually(ctx, session.Err).Should(gbytes.Say("Writing kubeconfig of the autonomous shoot to file"))
+ Eventually(ctx, session.Err).Should(gbytes.Say("Writing kubeconfig of the self-hosted shoot to file"))
// #nosec G304 -- kubeconfigOutputFile is controlled by the test
Expect(os.ReadFile(kubeconfigOutputFile)).To(ContainSubstring("server: https://api.root.garden.local.gardener.cloud"))
@@ -250,7 +250,7 @@ var _ = Describe("gardenadm medium-touch scenario tests", Label("gardenadm", "me
}, SpecTimeout(time.Minute))
It("should run successfully a second time (should be idempotent)", func(ctx SpecContext) {
- RunAndWait(ctx, "bootstrap", "-d", "../../../dev-setup/gardenadm/resources/generated/medium-touch")
+ RunAndWait(ctx, "bootstrap", "-d", "../../../dev-setup/gardenadm/resources/generated/managed-infra")
}, SpecTimeout(2*time.Minute))
})
})
diff --git a/test/e2e/gardenadm/hightouch/gardenadm.go b/test/e2e/gardenadm/unmanagedinfra/gardenadm.go
similarity index 97%
rename from test/e2e/gardenadm/hightouch/gardenadm.go
rename to test/e2e/gardenadm/unmanagedinfra/gardenadm.go
index e1ebfeab214..5d855321a9d 100644
--- a/test/e2e/gardenadm/hightouch/gardenadm.go
+++ b/test/e2e/gardenadm/unmanagedinfra/gardenadm.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
-package hightouch
+package unmanagedinfra
import (
"context"
@@ -34,7 +34,7 @@ import (
. "github.com/gardener/gardener/test/e2e/gardenadm/common"
)
-var _ = Describe("gardenadm high-touch scenario tests", Label("gardenadm", "high-touch"), func() {
+var _ = Describe("gardenadm unmanaged infrastructure scenario tests", Label("gardenadm", "unmanaged-infra"), func() {
var (
shootNamespace = "garden"
shootName = "root"
@@ -260,7 +260,7 @@ var _ = Describe("gardenadm high-touch scenario tests", Label("gardenadm", "high
}).Should(Succeed())
}, SpecTimeout(time.Minute))
- It("should generate a bootstrap token and connect the autonomous shoot to Gardener", func(ctx SpecContext) {
+ It("should generate a bootstrap token and connect the self-hosted shoot to Gardener", func(ctx SpecContext) {
stdOut, _, err := execute(ctx, 0, "sh", "-c", fmt.Sprintf("KUBECONFIG=%s gardenadm token create --print-connect-command --shoot-namespace=%s --shoot-name=%s", gardenClusterKubeconfigPathOnMachine, shootNamespace, shootName))
Expect(err).NotTo(HaveOccurred())
connectCommand := strings.Split(strings.ReplaceAll(string(stdOut.Contents()), `"`, ``), " ")
@@ -268,7 +268,7 @@ var _ = Describe("gardenadm high-touch scenario tests", Label("gardenadm", "high
stdOut, _, err = execute(ctx, 0, append(connectCommand, "--log-level=debug")...)
Expect(err).NotTo(HaveOccurred())
- Eventually(ctx, stdOut).Should(gbytes.Say("Your autonomous shoot cluster has successfully been connected to Gardener!"))
+ Eventually(ctx, stdOut).Should(gbytes.Say("Your self-hosted shoot cluster has successfully been connected to Gardener!"))
Eventually(ctx, func(g Gomega) {
csrList := &certificatesv1.CertificateSigningRequestList{}
diff --git a/test/e2e/gardenadm/hightouch/helper.go b/test/e2e/gardenadm/unmanagedinfra/helper.go
similarity index 80%
rename from test/e2e/gardenadm/hightouch/helper.go
rename to test/e2e/gardenadm/unmanagedinfra/helper.go
index 10b649fc584..253a0bffde9 100644
--- a/test/e2e/gardenadm/hightouch/helper.go
+++ b/test/e2e/gardenadm/unmanagedinfra/helper.go
@@ -2,14 +2,14 @@
//
// SPDX-License-Identifier: Apache-2.0
-package hightouch
+package unmanagedinfra
import (
"strconv"
)
const (
- namespace = "gardenadm-high-touch"
+ namespace = "gardenadm-unmanaged-infra"
statefulSetName = "machine"
)
diff --git a/test/integration/controllermanager/certificatesigningrequest/certificatesigningrequest_test.go b/test/integration/controllermanager/certificatesigningrequest/certificatesigningrequest_test.go
index e6a7dee39c5..7bf1f9c9a89 100644
--- a/test/integration/controllermanager/certificatesigningrequest/certificatesigningrequest_test.go
+++ b/test/integration/controllermanager/certificatesigningrequest/certificatesigningrequest_test.go
@@ -126,7 +126,7 @@ var _ = Describe("CSR autoapprove controller tests", func() {
Labels: map[string]string{testID: testRunID},
},
Data: map[string][]byte{
- "description": []byte(fmt.Sprintf("Used for connecting the autonomous Shoot %s/%s", shootNamespace, shootName)),
+ "description": []byte(fmt.Sprintf("Used for connecting the self-hosted Shoot %s/%s", shootNamespace, shootName)),
},
}
@@ -175,7 +175,7 @@ var _ = Describe("CSR autoapprove controller tests", func() {
Labels: map[string]string{testID: testRunID},
},
Data: map[string][]byte{
- "description": []byte(fmt.Sprintf("Used for connecting the autonomous Shoot %s/%s", shootNamespace, shootName)),
+ "description": []byte(fmt.Sprintf("Used for connecting the self-hosted Shoot %s/%s", shootNamespace, shootName)),
},
}
diff --git a/test/integration/gardenlet/controllerinstallation/controllerinstallation/controllerinstallation_test.go b/test/integration/gardenlet/controllerinstallation/controllerinstallation/controllerinstallation_test.go
index fd708901b0a..f78eac4ed2d 100644
--- a/test/integration/gardenlet/controllerinstallation/controllerinstallation/controllerinstallation_test.go
+++ b/test/integration/gardenlet/controllerinstallation/controllerinstallation/controllerinstallation_test.go
@@ -513,21 +513,21 @@ var _ = Describe("ControllerInstallation controller tests", func() {
})
})
- When("seed is marked as autonomous shoot clusters", func() {
+ When("seed is marked as self-hosted shoot clusters", func() {
BeforeEach(func() {
- By("Mark Seed as autonomous shoot cluster")
+ By("Mark Seed as self-hosted shoot cluster")
patch := client.MergeFrom(seed.DeepCopy())
- metav1.SetMetaDataLabel(&seed.ObjectMeta, "seed.gardener.cloud/autonomous-shoot-cluster", "true")
+ metav1.SetMetaDataLabel(&seed.ObjectMeta, "seed.gardener.cloud/self-hosted-shoot-cluster", "true")
Expect(testClient.Patch(ctx, seed, patch)).To(Succeed())
DeferCleanup(func() {
patch := client.MergeFrom(seed.DeepCopy())
- delete(seed.Labels, "seed.gardener.cloud/autonomous-shoot-cluster")
+ delete(seed.Labels, "seed.gardener.cloud/self-hosted-shoot-cluster")
Expect(testClient.Patch(ctx, seed, patch)).To(Succeed())
})
})
- It("should set the autonomousShootCluster value in the chart", func() {
+ It("should set the selfHostedShootCluster value in the chart", func() {
values := make(map[string]any)
Eventually(func(g Gomega) {
managedResource := &resourcesv1alpha1.ManagedResource{}
@@ -544,7 +544,7 @@ var _ = Describe("ControllerInstallation controller tests", func() {
valuesBytes, err := yaml.Marshal(values)
Expect(err).NotTo(HaveOccurred())
- Expect(string(valuesBytes)).To(ContainSubstring("autonomousShootCluster: true"))
+ Expect(string(valuesBytes)).To(ContainSubstring("selfHostedShootCluster: true"))
})
})
From eb844357ee6ccb01b0cb8b844ca56501556cbb8f Mon Sep 17 00:00:00 2001
From: Rada Dimitrova <117522044+RadaBDimitrova@users.noreply.github.com>
Date: Fri, 31 Oct 2025 18:37:11 +0200
Subject: [PATCH 013/176] Bump `vertical-pod-autoscaler` dependency from
`1.4.2` to `1.5.1` (#13315)
---
go.mod | 15 +++++++--------
go.sum | 28 ++++++++++++++--------------
2 files changed, 21 insertions(+), 22 deletions(-)
diff --git a/go.mod b/go.mod
index 6402cf360d3..0f376e35c27 100644
--- a/go.mod
+++ b/go.mod
@@ -66,8 +66,7 @@ require (
k8s.io/apiextensions-apiserver v0.34.1
k8s.io/apimachinery v0.34.1
k8s.io/apiserver v0.34.1
- // TODO(vitanovs): Update k8s.io/autoscaler/vertical-pod-autoscaler to v1.5.1 once https://github.com/gardener/gardener/issues/13162 is resolved.
- k8s.io/autoscaler/vertical-pod-autoscaler v1.4.2
+ k8s.io/autoscaler/vertical-pod-autoscaler v1.5.1
k8s.io/cli-runtime v0.34.1
k8s.io/client-go v0.34.1
k8s.io/cluster-bootstrap v0.34.1
@@ -76,7 +75,7 @@ require (
k8s.io/component-helpers v0.34.1
k8s.io/klog/v2 v2.130.1
k8s.io/kube-aggregator v0.34.1
- k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b
+ k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3
k8s.io/kube-proxy v0.34.1
k8s.io/kube-state-metrics/v2 v2.13.0
k8s.io/kubelet v0.34.1
@@ -130,7 +129,7 @@ require (
github.com/docker/docker-credential-helpers v0.8.2 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/docker/go-metrics v0.0.1 // indirect
- github.com/emicklei/go-restful/v3 v3.12.2 // indirect
+ github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
@@ -139,7 +138,7 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/errors v0.22.0 // indirect
- github.com/go-openapi/jsonpointer v0.21.1 // indirect
+ github.com/go-openapi/jsonpointer v0.21.2 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
@@ -270,19 +269,19 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/grpc v1.75.0 // indirect
- gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
+ gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect
- k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect
+ k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d // indirect
k8s.io/klog v1.0.0 // indirect
k8s.io/kms v0.34.1 // indirect
k8s.io/sample-controller v0.30.3 // indirect
oras.land/oras-go/v2 v2.6.0 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
- sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
+ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
)
diff --git a/go.sum b/go.sum
index 3b8452fd296..4004cecb47d 100644
--- a/go.sum
+++ b/go.sum
@@ -204,8 +204,8 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
-github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
-github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
+github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -273,8 +273,8 @@ github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUy
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
-github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
+github.com/go-openapi/jsonpointer v0.21.2 h1:AqQaNADVwq/VnkCmQg6ogE+M3FOsKTytwges0JdwVuA=
+github.com/go-openapi/jsonpointer v0.21.2/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
@@ -1052,8 +1052,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
-gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
+gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
+gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
@@ -1094,8 +1094,8 @@ k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4=
k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA=
k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0=
-k8s.io/autoscaler/vertical-pod-autoscaler v1.4.2 h1:47RLgLhrxXfdBchTeNT2S9Xe9o+Y4kThExLfcGGUQMk=
-k8s.io/autoscaler/vertical-pod-autoscaler v1.4.2/go.mod h1:rIBiAf+sK2mw8ryeHIZuY5juhJ4e2rNLwo59SDRXF7I=
+k8s.io/autoscaler/vertical-pod-autoscaler v1.5.1 h1:LlVtM3IKqIVHz1ZXC3ahe/mAtDWb7Eob0tyTzqFULqg=
+k8s.io/autoscaler/vertical-pod-autoscaler v1.5.1/go.mod h1:znhUnV0Yn+CkZu3TZ2HVqd8GFRMkPj/CXszX1gdBjTU=
k8s.io/cli-runtime v0.34.1 h1:btlgAgTrYd4sk8vJTRG6zVtqBKt9ZMDeQZo2PIzbL7M=
k8s.io/cli-runtime v0.34.1/go.mod h1:aVA65c+f0MZiMUPbseU/M9l1Wo2byeaGwUuQEQVVveE=
k8s.io/client-go v0.19.0/go.mod h1:H9E/VT95blcFQnlyShFgnFT9ZnJOAceiUHM3MlRC+mU=
@@ -1115,8 +1115,8 @@ k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks=
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
-k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f h1:SLb+kxmzfA87x4E4brQzB33VBbT2+x7Zq9ROIHmGn9Q=
-k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
+k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d h1:qUrYOinhdAUL0xxhA4gPqogPBaS9nIq2l2kTb6pmeB0=
+k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
@@ -1129,8 +1129,8 @@ k8s.io/kms v0.34.1/go.mod h1:s1CFkLG7w9eaTYvctOxosx88fl4spqmixnNpys0JAtM=
k8s.io/kube-aggregator v0.34.1 h1:WNLV0dVNoFKmuyvdWLd92iDSyD/TSTjqwaPj0U9XAEU=
k8s.io/kube-aggregator v0.34.1/go.mod h1:RU8j+5ERfp0h+gIvWtxRPfsa5nK7rboDm8RST8BJfYQ=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
-k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=
-k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
+k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 h1:liMHz39T5dJO1aOKHLvwaCjDbf07wVh6yaUlTpunnkE=
+k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
k8s.io/kube-proxy v0.34.1 h1:cIriNCJY5XmRhXCCyQiazyqi47lbwcBQf0H76fVOpkw=
k8s.io/kube-proxy v0.34.1/go.mod h1:syed9c5+gUVFMo6p24SnlTHzsp+BMd4ACcTw2dbArw0=
k8s.io/kube-state-metrics/v2 v2.13.0 h1:g5OV0cwrDKvyrQApYxI7Ny+vFUgU3X6MYrnIzdCAdNU=
@@ -1157,8 +1157,8 @@ sigs.k8s.io/controller-tools v0.19.0 h1:OU7jrPPiZusryu6YK0jYSjPqg8Vhf8cAzluP9XGI
sigs.k8s.io/controller-tools v0.19.0/go.mod h1:y5HY/iNDFkmFla2CfQoVb2AQXMsBk4ad84iR1PLANB0=
sigs.k8s.io/gateway-api v1.3.0 h1:q6okN+/UKDATola4JY7zXzx40WO4VISk7i9DIfOvr9M=
sigs.k8s.io/gateway-api v1.3.0/go.mod h1:d8NV8nJbaRbEKem+5IuxkL8gJGOZ+FJ+NvOIltV8gDk=
-sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
-sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
+sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
+sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
From c5e73670a1a11d1e50b4de5857dc06fad97edd88 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Fri, 31 Oct 2025 20:43:04 +0100
Subject: [PATCH 014/176] Update quay.io/kiwigrid/k8s-sidecar Docker tag to v2
(#13288)
---
imagevector/containers.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index fdbaa6c03d3..93ad7b214e8 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -337,7 +337,7 @@ images:
- name: plutono-data-refresher
sourceRepository: github.com/kiwigrid/k8s-sidecar
repository: quay.io/kiwigrid/k8s-sidecar
- tag: "1.30.9"
+ tag: "2.0.3"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
From ebe0588fa0083429746d5d063f668e91eb831720 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Fri, 31 Oct 2025 20:43:12 +0100
Subject: [PATCH 015/176] Update dependency crate-ci/typos to v1.39.0 (#13320)
---
hack/tools.mk | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hack/tools.mk b/hack/tools.mk
index 69b5c6b0515..876511c8741 100644
--- a/hack/tools.mk
+++ b/hack/tools.mk
@@ -83,7 +83,7 @@ YQ_VERSION ?= v4.48.1
# renovate: datasource=github-releases depName=ironcore-dev/vgopath
VGOPATH_VERSION ?= v0.1.9
# renovate: datasource=github-releases depName=crate-ci/typos
-TYPOS_VERSION ?= v1.38.1
+TYPOS_VERSION ?= v1.39.0
# tool versions from go.mod
CONTROLLER_GEN_VERSION ?= $(call version_gomod,sigs.k8s.io/controller-tools)
From 52f5105c6505f21352ba613ee84fdfff70de747d Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Sun, 2 Nov 2025 17:53:57 +0100
Subject: [PATCH 016/176] Update
registry.k8s.io/ingress-nginx/controller-chroot Docker tag to v1.13.4
(#13318)
---
imagevector/containers.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index 93ad7b214e8..3690190f464 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -86,7 +86,7 @@ images:
- name: nginx-ingress-controller
sourceRepository: github.com/kubernetes/ingress-nginx
repository: registry.k8s.io/ingress-nginx/controller-chroot
- tag: "v1.13.3"
+ tag: "v1.13.4"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
From 893729010e2e1112c3411cca0e447c43c6e1a669 Mon Sep 17 00:00:00 2001
From: Sonu Kumar Singh
Date: Mon, 3 Nov 2025 15:58:59 +0530
Subject: [PATCH 017/176] Validate issuer URLs in ServiceAccountConfig (#13325)
---
pkg/apis/core/validation/shoot.go | 7 ++++-
pkg/apis/core/validation/shoot_test.go | 43 +++++++++++++++++++++++---
2 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/pkg/apis/core/validation/shoot.go b/pkg/apis/core/validation/shoot.go
index 80be1449b40..66938606743 100644
--- a/pkg/apis/core/validation/shoot.go
+++ b/pkg/apis/core/validation/shoot.go
@@ -1665,14 +1665,19 @@ func ValidateKubeAPIServer(kubeAPIServer *core.KubeAPIServerConfig, version stri
allErrs = append(allErrs, field.Forbidden(fldPath.Child("serviceAccountConfig", "maxTokenExpiration"), "must be at most 2160h (90d)"))
}
}
+
+ if kubeAPIServer.ServiceAccountConfig.Issuer != nil {
+ allErrs = append(allErrs, ValidateOIDCIssuerURL(*kubeAPIServer.ServiceAccountConfig.Issuer, fldPath.Child("serviceAccountConfig", "issuer"))...)
+ }
if len(kubeAPIServer.ServiceAccountConfig.AcceptedIssuers) > 0 {
issuers := sets.New[string]()
if kubeAPIServer.ServiceAccountConfig.Issuer != nil {
issuers.Insert(*kubeAPIServer.ServiceAccountConfig.Issuer)
}
for i, acceptedIssuer := range kubeAPIServer.ServiceAccountConfig.AcceptedIssuers {
+ path := fldPath.Child("serviceAccountConfig", "acceptedIssuers").Index(i)
+ allErrs = append(allErrs, ValidateOIDCIssuerURL(acceptedIssuer, path)...)
if issuers.Has(acceptedIssuer) {
- path := fldPath.Child("serviceAccountConfig", "acceptedIssuers").Index(i)
if issuer := kubeAPIServer.ServiceAccountConfig.Issuer; issuer != nil && *issuer == acceptedIssuer {
allErrs = append(allErrs, field.Invalid(path, acceptedIssuer, fmt.Sprintf("acceptedIssuers cannot contains the issuer field value: %s", acceptedIssuer)))
} else {
diff --git a/pkg/apis/core/validation/shoot_test.go b/pkg/apis/core/validation/shoot_test.go
index 55742d0b816..8e29a27cd5d 100644
--- a/pkg/apis/core/validation/shoot_test.go
+++ b/pkg/apis/core/validation/shoot_test.go
@@ -2891,8 +2891,8 @@ var _ = Describe("Shoot Validation Tests", func() {
It("should not allow to specify duplicates in accepted issuers", func() {
shoot.Spec.Kubernetes.KubeAPIServer.ServiceAccountConfig = &core.ServiceAccountConfig{
AcceptedIssuers: []string{
- "foo",
- "foo",
+ "https://issuer.example/auth",
+ "https://issuer.example/auth",
},
}
@@ -2906,8 +2906,8 @@ var _ = Describe("Shoot Validation Tests", func() {
It("should not allow to duplicate the issuer in accepted issuers", func() {
shoot.Spec.Kubernetes.KubeAPIServer.ServiceAccountConfig = &core.ServiceAccountConfig{
- Issuer: ptr.To("foo"),
- AcceptedIssuers: []string{"foo"},
+ Issuer: ptr.To("https://issuer.example/auth"),
+ AcceptedIssuers: []string{"https://issuer.example/auth"},
}
errorList := ValidateShoot(shoot)
@@ -2915,9 +2915,42 @@ var _ = Describe("Shoot Validation Tests", func() {
Expect(errorList).To(ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.kubernetes.kubeAPIServer.serviceAccountConfig.acceptedIssuers[0]"),
- "Detail": ContainSubstring("acceptedIssuers cannot contains the issuer field value: foo"),
+ "Detail": ContainSubstring("acceptedIssuers cannot contains the issuer field value: https://issuer.example/auth"),
}))))
})
+
+ It("should reject invalid issuer URL", func() {
+ shoot.Spec.Kubernetes.KubeAPIServer.ServiceAccountConfig = &core.ServiceAccountConfig{
+ Issuer: ptr.To("http://issuer.invalid"),
+ }
+
+ errorList := ValidateShoot(shoot)
+
+ Expect(errorList).To(ContainElement(PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.kubernetes.kubeAPIServer.serviceAccountConfig.issuer"),
+ }))))
+ })
+
+ DescribeTable("should reject invalid accepted issuer URLs",
+ func(bad string) {
+ shoot.Spec.Kubernetes.KubeAPIServer.ServiceAccountConfig = &core.ServiceAccountConfig{
+ AcceptedIssuers: []string{bad},
+ }
+
+ errorList := ValidateShoot(shoot)
+
+ Expect(errorList).To(ContainElement(PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.kubernetes.kubeAPIServer.serviceAccountConfig.acceptedIssuers[0]"),
+ }))))
+ },
+ Entry("plain string", "foo"),
+ Entry("non-https scheme", "http://issuer.com"),
+ Entry("contains fragment", "https://issuer.com#fragment"),
+ Entry("contains userinfo", "https://user:pass@issuer.com"),
+ Entry("contains query", "https://issuer.com?x=1"),
+ )
})
Context("Autoscaling validation", func() {
From 6c7f9595a3fec74a3eca667172fcd55e1373d1b0 Mon Sep 17 00:00:00 2001
From: Johannes Roncossek <140696835+Roncossek@users.noreply.github.com>
Date: Mon, 3 Nov 2025 15:00:14 +0100
Subject: [PATCH 018/176] [GEP-33] Ensure `NamespacedCloudProfile` status
format (#13138)
* fix: defaulting strategy and validation for cloudprofiles using one architecture
* feat: ensure uniform format for machine images in NamespacedCloudProfile for provider local
* feat: implement ensureUniformFormat to synchronize NamespacedCloudProfile with parent CloudProfile
* feat: simplify scope of initialMigration to machineCapabilities
* adhere to repository standards and other review feedback
* feat: simplify scope of initialMigration to machineCapabilities
* move restrictToArchitectureCapability function and refine architecture syncing logic
* fix: GetArchitecture uses capability definitions
* feat: simulate transformation of namespacedcloudprofile format during admission webhook
* refactor: move GetCapabilitiesWithAppliedDefaults to types and simplify GetArchitecture handling
* feat: clear capability flavors during migration to legacy format
* feat: implement simulation of transformation to parent spec format for NamespacedCloudProfile admission pligin
* feat: add reference validation for removing machine capabilities in CloudProfile
* adhere to review comments
* test: update machine image expectations to use ConsistOf matcher
---
docs/api-reference/provider-local.md | 1 +
.../33-machine-image-capabilities.md | 14 +-
.../pkg/controller/worker/cloudprofile.go | 2 +-
pkg/apis/core/helper/cloudprofile.go | 21 +-
pkg/apis/core/helper/cloudprofile_test.go | 40 +-
pkg/apis/core/types_cloudprofile.go | 30 +-
pkg/apis/core/types_test.go | 33 ++
pkg/apis/core/v1beta1/helper/cloudprofile.go | 25 +-
.../core/v1beta1/helper/cloudprofile_test.go | 34 --
pkg/apis/core/v1beta1/types_cloudprofile.go | 47 +--
pkg/apis/core/v1beta1/types_test.go | 34 ++
pkg/apis/core/validation/cloudprofile.go | 46 ++-
pkg/apis/core/validation/cloudprofile_test.go | 57 ++-
pkg/apis/core/validation/utils.go | 173 ++++----
.../core/cloudprofile/strategy_test.go | 3 +-
.../namespacedcloudprofile/reconciler.go | 38 +-
.../namespacedcloudprofile/reconciler_test.go | 267 +++++++++++-
.../mutator/namespacedcloudprofile.go | 31 +-
.../mutator/namespacedcloudprofile_test.go | 84 +++-
.../admission/validator/cloudprofile.go | 6 +-
.../validator/namespacedcloudprofile.go | 37 ++
.../apis/local/v1alpha1/types_cloudprofile.go | 3 +-
.../apis/local/validation/cloudprofile.go | 8 +-
.../controller/worker/machine_images.go | 4 +-
pkg/utils/gardener/cloudprofile.go | 147 ++++---
pkg/utils/gardener/cloudprofile_test.go | 120 ++++--
pkg/utils/gardener/namespacedcloudprofile.go | 87 ++++
.../gardener/namespacedcloudprofile_test.go | 380 ++++++++++++++++++
.../resourcereferencemanager/admission.go | 66 ++-
.../admission_test.go | 232 +++++++++++
.../validator/admission.go | 63 ++-
.../validator/admission_test.go | 225 +++++++----
plugin/pkg/shoot/validator/admission.go | 2 +-
plugin/pkg/shoot/validator/admission_test.go | 2 +-
skaffold-operator.yaml | 6 +
.../namespacedcloudprofile_test.go | 50 +--
36 files changed, 1930 insertions(+), 488 deletions(-)
create mode 100644 pkg/utils/gardener/namespacedcloudprofile.go
create mode 100644 pkg/utils/gardener/namespacedcloudprofile_test.go
diff --git a/docs/api-reference/provider-local.md b/docs/api-reference/provider-local.md
index f416bfb0db6..8392c2647f8 100644
--- a/docs/api-reference/provider-local.md
+++ b/docs/api-reference/provider-local.md
@@ -251,6 +251,7 @@ string
+(Optional)
Image is the image for the machine image.
diff --git a/docs/proposals/33-machine-image-capabilities.md b/docs/proposals/33-machine-image-capabilities.md
index b1364a17b8d..3aa92a8fe17 100644
--- a/docs/proposals/33-machine-image-capabilities.md
+++ b/docs/proposals/33-machine-image-capabilities.md
@@ -188,14 +188,14 @@ In this case it does not result in an error but in performance loss.
## Proposal
-Introduce a top level capabilities array in the CloudProfile `spec.capabilities`.
+Introduce a top level array in the CloudProfile `spec.machineCapabilities`.
```go
type Spec struct {
- Capabilities []Capability
+ MachineCapabilities []CapabilityDefinition
}
-type Capability struct {
+type CapabilityDefinition struct {
Name string
Values []string
}
@@ -205,7 +205,7 @@ Capabilities are very specific to the provider and the selected catalog offered
To minimize complexity and data size in the cloud profile, the capabilities are defined as a map with string keys and string arrays as values.
The key is the capability name and the value is an array of possible values.
-For each cloud profile the capabilities are defined in the `spec.capabilities` array.
+For each cloud profile the capabilities are defined in the `spec.machineCapabilities` array.
The full set of possibilities for each capability is defined here.
As some capabilities can have multiple values at the same time an array of possible values is used instead of a single value.
@@ -215,7 +215,7 @@ If no further information is provided each machine type and machine image will b
```yaml
# CloudProfile Example
spec:
- capabilities:
+ machineCapabilities:
- name: architecture
values: [amd64, arm64]
- name: hypervisorType
@@ -255,7 +255,7 @@ The architecture is also added to the image version capability flavors. This is
```yaml
# CloudProfile
spec:
- capabilities: # <-- Full list of possible capabilities used as default
+ machineCapabilities: # <-- Full list of possible capabilities used as default
- name: architecture
values: [amd64]
- name: hypervisorType
@@ -361,7 +361,7 @@ If multiple machine image versions are valid for a machine type, the selection i
The following implications are to be considered in regards to `NamespacedCloudProfile`s:
-* `NamespacedCloudProfile`s won't have a global `capabilities` definition.
+* `NamespacedCloudProfile`s won't have a global `machineCapabilities` definition.
* For overridden machine image versions, no `capabilities` must be defined, as they are inherited from the machine image versions of the parent `CloudProfile`.
* For custom machine image versions, the `capabilities` need to be defined in the `NamespacedCloudProfile`, as they would be in the `CloudProfile` (as well as for the `providerConfig`).
diff --git a/extensions/pkg/controller/worker/cloudprofile.go b/extensions/pkg/controller/worker/cloudprofile.go
index 503215aa939..4758cc8f6e5 100644
--- a/extensions/pkg/controller/worker/cloudprofile.go
+++ b/extensions/pkg/controller/worker/cloudprofile.go
@@ -78,7 +78,7 @@ func selectBestImageFlavor[T CapabilitiesAccessor](
capabilitiesWithProviderTypes = append(capabilitiesWithProviderTypes, capabilitiesWithProviderType{
providerEntry: set,
// Normalize capabilities copy by applying defaults
- capabilities: v1beta1helper.GetCapabilitiesWithAppliedDefaults(set.GetCapabilities(), capabilityDefinitions),
+ capabilities: v1beta1.GetCapabilitiesWithAppliedDefaults(set.GetCapabilities(), capabilityDefinitions),
})
}
diff --git a/pkg/apis/core/helper/cloudprofile.go b/pkg/apis/core/helper/cloudprofile.go
index 18b8745a293..26722737cb5 100644
--- a/pkg/apis/core/helper/cloudprofile.go
+++ b/pkg/apis/core/helper/cloudprofile.go
@@ -282,30 +282,17 @@ func CapabilityDefinitionsToCapabilities(capabilityDefinitions []core.Capability
return capabilities
}
-// GetCapabilitiesWithAppliedDefaults returns new capabilities with applied defaults from the capability definitions.
-func GetCapabilitiesWithAppliedDefaults(capabilities core.Capabilities, capabilityDefinitions []core.CapabilityDefinition) core.Capabilities {
- result := make(core.Capabilities, len(capabilityDefinitions))
- for _, capabilityDefinition := range capabilityDefinitions {
- if values, ok := capabilities[capabilityDefinition.Name]; ok {
- result[capabilityDefinition.Name] = values
- } else {
- result[capabilityDefinition.Name] = capabilityDefinition.Values
- }
- }
- return result
-}
-
-// GetImageFlavorWithAppliedDefaults returns MachineImageFlavors sets with applied defaults from the capability definitions.
-func GetImageFlavorWithAppliedDefaults(imageFlavors []core.MachineImageFlavor, capabilityDefinitions []core.CapabilityDefinition) []core.MachineImageFlavor {
+// GetImageFlavorsWithAppliedDefaults returns MachineImageFlavors sets with applied defaults from the capability definitions.
+func GetImageFlavorsWithAppliedDefaults(imageFlavors []core.MachineImageFlavor, capabilityDefinitions []core.CapabilityDefinition) []core.MachineImageFlavor {
if len(imageFlavors) == 0 {
// If no capabilityFlavors are defined, assume all capabilities are supported.
- return []core.MachineImageFlavor{{Capabilities: GetCapabilitiesWithAppliedDefaults(core.Capabilities{}, capabilityDefinitions)}}
+ return []core.MachineImageFlavor{{Capabilities: core.GetCapabilitiesWithAppliedDefaults(core.Capabilities{}, capabilityDefinitions)}}
}
result := make([]core.MachineImageFlavor, len(imageFlavors))
for i, imageFlavor := range imageFlavors {
result[i] = core.MachineImageFlavor{
- Capabilities: GetCapabilitiesWithAppliedDefaults(imageFlavor.Capabilities, capabilityDefinitions),
+ Capabilities: core.GetCapabilitiesWithAppliedDefaults(imageFlavor.Capabilities, capabilityDefinitions),
}
}
return result
diff --git a/pkg/apis/core/helper/cloudprofile_test.go b/pkg/apis/core/helper/cloudprofile_test.go
index bf0f9533b19..7cabf2d987a 100644
--- a/pkg/apis/core/helper/cloudprofile_test.go
+++ b/pkg/apis/core/helper/cloudprofile_test.go
@@ -518,41 +518,7 @@ var _ = Describe("CloudProfile Helper", func() {
Entry("with capabilities", "architecture", "network"),
)
- Describe("#GetCapabilitiesWithAppliedDefaults", func() {
- It("should apply default values when capabilities are nil", func() {
- var capabilities core.Capabilities
- capabilityDefinitions := []core.CapabilityDefinition{
- {Name: "capability1", Values: []string{"value1", "value2"}},
- {Name: "architecture", Values: []string{"amd64"}},
- }
-
- result := GetCapabilitiesWithAppliedDefaults(capabilities, capabilityDefinitions)
-
- Expect(result).To(Equal(core.Capabilities{
- "capability1": []string{"value1", "value2"},
- "architecture": []string{"amd64"},
- }))
- })
-
- It("should retain existing values and apply defaults for missing capabilities", func() {
- capabilities := core.Capabilities{
- "capability1": []string{"value1"},
- }
- capabilityDefinitions := []core.CapabilityDefinition{
- {Name: "capability1", Values: []string{"value1", "value2"}},
- {Name: "architecture", Values: []string{"amd64"}},
- }
-
- result := GetCapabilitiesWithAppliedDefaults(capabilities, capabilityDefinitions)
-
- Expect(result).To(Equal(core.Capabilities{
- "capability1": []string{"value1"},
- "architecture": []string{"amd64"},
- }))
- })
- })
-
- Describe("#GetImageFlavorWithAppliedDefaults", func() {
+ Describe("#GetImageFlavorsWithAppliedDefaults", func() {
It("should apply defaults when capabilityFlavors are empty", func() {
var imageFlavors []core.MachineImageFlavor
capabilityDefinitions := []core.CapabilityDefinition{
@@ -560,7 +526,7 @@ var _ = Describe("CloudProfile Helper", func() {
{Name: "architecture", Values: []string{"amd64"}},
}
- result := GetImageFlavorWithAppliedDefaults(imageFlavors, capabilityDefinitions)
+ result := GetImageFlavorsWithAppliedDefaults(imageFlavors, capabilityDefinitions)
Expect(result).To(HaveLen(1))
Expect(result[0].Capabilities).To(Equal(core.Capabilities{
@@ -579,7 +545,7 @@ var _ = Describe("CloudProfile Helper", func() {
{Name: "architecture", Values: []string{"amd64", "arm64"}},
}
- result := GetImageFlavorWithAppliedDefaults(imageFlavors, capabilityDefinitions)
+ result := GetImageFlavorsWithAppliedDefaults(imageFlavors, capabilityDefinitions)
Expect(result).To(HaveLen(2))
Expect(result[0].Capabilities).To(Equal(core.Capabilities{
diff --git a/pkg/apis/core/types_cloudprofile.go b/pkg/apis/core/types_cloudprofile.go
index 9fc9794f765..d03c2986b4e 100644
--- a/pkg/apis/core/types_cloudprofile.go
+++ b/pkg/apis/core/types_cloudprofile.go
@@ -173,14 +173,6 @@ type MachineType struct {
Capabilities Capabilities
}
-// GetArchitecture returns the architecture of the machine type.
-func (m *MachineType) GetArchitecture() string {
- if len(m.Capabilities[constants.ArchitectureName]) == 1 {
- return m.Capabilities[constants.ArchitectureName][0]
- }
- return ptr.Deref(m.Architecture, "")
-}
-
// MachineTypeStorage is the amount of storage associated with the root volume of this machine type.
type MachineTypeStorage struct {
// Class is the class of the storage type.
@@ -332,3 +324,25 @@ type Capabilities map[string]CapabilityValues
type MachineImageFlavor struct {
Capabilities
}
+
+// GetArchitecture returns the architecture of the machine type.
+func (m *MachineType) GetArchitecture(capabilityDefinitions []CapabilityDefinition) string {
+ capabilityArchitecture := GetCapabilitiesWithAppliedDefaults(m.Capabilities, capabilityDefinitions)[constants.ArchitectureName]
+ if len(capabilityArchitecture) == 1 {
+ return capabilityArchitecture[0]
+ }
+ return ptr.Deref(m.Architecture, "")
+}
+
+// GetCapabilitiesWithAppliedDefaults returns new capabilities with applied defaults from the capability definitions.
+func GetCapabilitiesWithAppliedDefaults(capabilities Capabilities, capabilityDefinitions []CapabilityDefinition) Capabilities {
+ result := make(Capabilities, len(capabilityDefinitions))
+ for _, capabilityDefinition := range capabilityDefinitions {
+ if values, ok := capabilities[capabilityDefinition.Name]; ok {
+ result[capabilityDefinition.Name] = values
+ } else {
+ result[capabilityDefinition.Name] = capabilityDefinition.Values
+ }
+ }
+ return result
+}
diff --git a/pkg/apis/core/types_test.go b/pkg/apis/core/types_test.go
index 3b43a01bac1..f85ea00df66 100644
--- a/pkg/apis/core/types_test.go
+++ b/pkg/apis/core/types_test.go
@@ -53,4 +53,37 @@ var _ = Describe("API Types", func() {
Entry("#ClassificationDeprecated is active", ClassificationDeprecated, true),
Entry("#ClassificationExpired is not active", ClassificationExpired, false),
)
+ Describe("#GetCapabilitiesWithAppliedDefaults", func() {
+ It("should apply default values when capabilities are nil", func() {
+ var capabilities Capabilities
+ capabilityDefinitions := []CapabilityDefinition{
+ {Name: "capability1", Values: []string{"value1", "value2"}},
+ {Name: "architecture", Values: []string{"amd64"}},
+ }
+
+ result := GetCapabilitiesWithAppliedDefaults(capabilities, capabilityDefinitions)
+
+ Expect(result).To(Equal(Capabilities{
+ "capability1": []string{"value1", "value2"},
+ "architecture": []string{"amd64"},
+ }))
+ })
+
+ It("should retain existing values and apply defaults for missing capabilities", func() {
+ capabilities := Capabilities{
+ "capability1": []string{"value1"},
+ }
+ capabilityDefinitions := []CapabilityDefinition{
+ {Name: "capability1", Values: []string{"value1", "value2"}},
+ {Name: "architecture", Values: []string{"amd64"}},
+ }
+
+ result := GetCapabilitiesWithAppliedDefaults(capabilities, capabilityDefinitions)
+
+ Expect(result).To(Equal(Capabilities{
+ "capability1": []string{"value1"},
+ "architecture": []string{"amd64"},
+ }))
+ })
+ })
})
diff --git a/pkg/apis/core/v1beta1/helper/cloudprofile.go b/pkg/apis/core/v1beta1/helper/cloudprofile.go
index 9c7d086c4db..91c94bb5791 100644
--- a/pkg/apis/core/v1beta1/helper/cloudprofile.go
+++ b/pkg/apis/core/v1beta1/helper/cloudprofile.go
@@ -533,7 +533,7 @@ func FilterDeprecatedVersion() func(expirableVersion gardencorev1beta1.Expirable
}
}
-func extractArchitecturesFromImageFlavor(imageFlavors []gardencorev1beta1.MachineImageFlavor, capabilityDefinitions []gardencorev1beta1.CapabilityDefinition) []string {
+func extractArchitecturesFromImageFlavors(imageFlavors []gardencorev1beta1.MachineImageFlavor, capabilityDefinitions []gardencorev1beta1.CapabilityDefinition) []string {
if len(imageFlavors) == 0 {
for _, capabilityDefinition := range capabilityDefinitions {
if capabilityDefinition.Name == constants.ArchitectureName {
@@ -554,7 +554,7 @@ func extractArchitecturesFromImageFlavor(imageFlavors []gardencorev1beta1.Machin
// GetArchitecturesFromImageVersion returns the list of supported architectures for the machine image version.
// It first tries to retrieve the architectures from the capability flavors and falls back to the architectures field if none are found.
func GetArchitecturesFromImageVersion(imageVersion gardencorev1beta1.MachineImageVersion, capabilityDefinitions []gardencorev1beta1.CapabilityDefinition) []string {
- if architectures := extractArchitecturesFromImageFlavor(imageVersion.CapabilityFlavors, capabilityDefinitions); len(architectures) > 0 {
+ if architectures := extractArchitecturesFromImageFlavors(imageVersion.CapabilityFlavors, capabilityDefinitions); len(architectures) > 0 {
return architectures
}
return imageVersion.Architectures
@@ -567,30 +567,17 @@ func ArchitectureSupportedByImageVersion(version gardencorev1beta1.MachineImageV
return slices.Contains(supportedArchitectures, architecture)
}
-// GetCapabilitiesWithAppliedDefaults returns new capabilities with applied defaults from the capability definitions.
-func GetCapabilitiesWithAppliedDefaults(capabilities gardencorev1beta1.Capabilities, capabilityDefinitions []gardencorev1beta1.CapabilityDefinition) gardencorev1beta1.Capabilities {
- result := make(gardencorev1beta1.Capabilities, len(capabilityDefinitions))
- for _, capabilityDefinition := range capabilityDefinitions {
- if values, ok := capabilities[capabilityDefinition.Name]; ok {
- result[capabilityDefinition.Name] = values
- } else {
- result[capabilityDefinition.Name] = capabilityDefinition.Values
- }
- }
- return result
-}
-
// GetImageFlavorsWithAppliedDefaults returns new MachineImageFlavors with applied defaults from the capability definitions.
func GetImageFlavorsWithAppliedDefaults(imageFlavors []gardencorev1beta1.MachineImageFlavor, capabilityDefinitions []gardencorev1beta1.CapabilityDefinition) []gardencorev1beta1.MachineImageFlavor {
if len(imageFlavors) == 0 {
// If no capabilityFlavors are defined, assume all capabilities are supported.
- return []gardencorev1beta1.MachineImageFlavor{{Capabilities: GetCapabilitiesWithAppliedDefaults(gardencorev1beta1.Capabilities{}, capabilityDefinitions)}}
+ return []gardencorev1beta1.MachineImageFlavor{{Capabilities: gardencorev1beta1.GetCapabilitiesWithAppliedDefaults(gardencorev1beta1.Capabilities{}, capabilityDefinitions)}}
}
result := make([]gardencorev1beta1.MachineImageFlavor, len(imageFlavors))
for i, imageFlavor := range imageFlavors {
result[i] = gardencorev1beta1.MachineImageFlavor{
- Capabilities: GetCapabilitiesWithAppliedDefaults(imageFlavor.Capabilities, capabilityDefinitions),
+ Capabilities: gardencorev1beta1.GetCapabilitiesWithAppliedDefaults(imageFlavor.Capabilities, capabilityDefinitions),
}
}
return result
@@ -649,8 +636,8 @@ func AreCapabilitiesSupportedByImageFlavors(
// AreCapabilitiesCompatible checks if two sets of capabilities are compatible.
// It applies defaults from the capability definitions to both sets before checking compatibility.
func AreCapabilitiesCompatible(capabilities1, capabilities2 gardencorev1beta1.Capabilities, capabilityDefinitions []gardencorev1beta1.CapabilityDefinition) bool {
- defaultedCapabilities1 := GetCapabilitiesWithAppliedDefaults(capabilities1, capabilityDefinitions)
- defaultedCapabilities2 := GetCapabilitiesWithAppliedDefaults(capabilities2, capabilityDefinitions)
+ defaultedCapabilities1 := gardencorev1beta1.GetCapabilitiesWithAppliedDefaults(capabilities1, capabilityDefinitions)
+ defaultedCapabilities2 := gardencorev1beta1.GetCapabilitiesWithAppliedDefaults(capabilities2, capabilityDefinitions)
isSupported := true
commonCapabilities := GetCapabilitiesIntersection(defaultedCapabilities1, defaultedCapabilities2)
diff --git a/pkg/apis/core/v1beta1/helper/cloudprofile_test.go b/pkg/apis/core/v1beta1/helper/cloudprofile_test.go
index 455fb86fd33..029e10bb385 100644
--- a/pkg/apis/core/v1beta1/helper/cloudprofile_test.go
+++ b/pkg/apis/core/v1beta1/helper/cloudprofile_test.go
@@ -1506,40 +1506,6 @@ var _ = Describe("CloudProfile Helper", func() {
Entry("Should be true for supported architecture", []string{"amd64", "arm64"}, "arm64", true),
)
- Describe("#GetCapabilitiesWithAppliedDefaults", func() {
- It("should apply default values when capabilities are nil", func() {
- var capabilities gardencorev1beta1.Capabilities
- capabilityDefinitions := []gardencorev1beta1.CapabilityDefinition{
- {Name: "capability1", Values: []string{"value1", "value2"}},
- {Name: "architecture", Values: []string{"amd64"}},
- }
-
- result := GetCapabilitiesWithAppliedDefaults(capabilities, capabilityDefinitions)
-
- Expect(result).To(Equal(gardencorev1beta1.Capabilities{
- "capability1": []string{"value1", "value2"},
- "architecture": []string{"amd64"},
- }))
- })
-
- It("should retain existing values and apply defaults for missing capabilities", func() {
- capabilities := gardencorev1beta1.Capabilities{
- "capability1": []string{"value1"},
- }
- capabilityDefinitions := []gardencorev1beta1.CapabilityDefinition{
- {Name: "capability1", Values: []string{"value1", "value2"}},
- {Name: "architecture", Values: []string{"amd64"}},
- }
-
- result := GetCapabilitiesWithAppliedDefaults(capabilities, capabilityDefinitions)
-
- Expect(result).To(Equal(gardencorev1beta1.Capabilities{
- "capability1": []string{"value1"},
- "architecture": []string{"amd64"},
- }))
- })
- })
-
Describe("#GetImageFlavorsWithAppliedDefaults", func() {
It("should apply defaults when capabilityFlavors are empty", func() {
var imageFlavors []gardencorev1beta1.MachineImageFlavor
diff --git a/pkg/apis/core/v1beta1/types_cloudprofile.go b/pkg/apis/core/v1beta1/types_cloudprofile.go
index 821e4127a4b..97b45fa3f11 100644
--- a/pkg/apis/core/v1beta1/types_cloudprofile.go
+++ b/pkg/apis/core/v1beta1/types_cloudprofile.go
@@ -196,31 +196,6 @@ type MachineType struct {
Capabilities Capabilities `json:"capabilities,omitempty" protobuf:"bytes,8,rep,name=capabilities,casttype=Capabilities"`
}
-// GetArchitecture returns the architecture of the machine type.
-func (m *MachineType) GetArchitecture(capabilityDefinitions []CapabilityDefinition) string {
- if len(capabilityDefinitions) == 0 {
- return ptr.Deref(m.Architecture, "")
- }
-
- if len(m.Capabilities[constants.ArchitectureName]) == 1 {
- return m.Capabilities[constants.ArchitectureName][0]
- }
-
- if len(m.Capabilities[constants.ArchitectureName]) == 0 {
- for _, capabilityDefinition := range capabilityDefinitions {
- if capabilityDefinition.Name == constants.ArchitectureName && len(capabilityDefinition.Values) == 1 {
- return capabilityDefinition.Values[0]
- }
- }
- }
-
- // constants.ArchitectureName is a required capability and
- // machineType.Capabilities[constants.ArchitectureName] can only
- // be empty for cloudprofiles supporting exactly one architecture.
- // we should never reach this point.
- return ""
-}
-
// MachineTypeStorage is the amount of storage associated with the root volume of this machine type.
type MachineTypeStorage struct {
// Class is the class of the storage type.
@@ -409,3 +384,25 @@ func (c *MachineImageFlavor) UnmarshalJSON(data []byte) error {
func (c *MachineImageFlavor) MarshalJSON() ([]byte, error) {
return json.Marshal(c.Capabilities)
}
+
+// GetArchitecture returns the architecture of the machine type.
+func (m *MachineType) GetArchitecture(capabilityDefinitions []CapabilityDefinition) string {
+ capabilityArchitecture := GetCapabilitiesWithAppliedDefaults(m.Capabilities, capabilityDefinitions)[constants.ArchitectureName]
+ if len(capabilityArchitecture) == 1 {
+ return capabilityArchitecture[0]
+ }
+ return ptr.Deref(m.Architecture, "")
+}
+
+// GetCapabilitiesWithAppliedDefaults returns new capabilities with applied defaults from the capability definitions.
+func GetCapabilitiesWithAppliedDefaults(capabilities Capabilities, capabilityDefinitions []CapabilityDefinition) Capabilities {
+ result := make(Capabilities, len(capabilityDefinitions))
+ for _, capabilityDefinition := range capabilityDefinitions {
+ if values, ok := capabilities[capabilityDefinition.Name]; ok {
+ result[capabilityDefinition.Name] = values
+ } else {
+ result[capabilityDefinition.Name] = capabilityDefinition.Values
+ }
+ }
+ return result
+}
diff --git a/pkg/apis/core/v1beta1/types_test.go b/pkg/apis/core/v1beta1/types_test.go
index 9a137b511fe..3ffd5946408 100644
--- a/pkg/apis/core/v1beta1/types_test.go
+++ b/pkg/apis/core/v1beta1/types_test.go
@@ -53,4 +53,38 @@ var _ = Describe("Types", func() {
Entry("#ClassificationDeprecated is active", ClassificationDeprecated, true),
Entry("#ClassificationExpired is not active", ClassificationExpired, false),
)
+
+ Describe("#GetCapabilitiesWithAppliedDefaults", func() {
+ It("should apply default values when capabilities are nil", func() {
+ var capabilities Capabilities
+ capabilityDefinitions := []CapabilityDefinition{
+ {Name: "capability1", Values: []string{"value1", "value2"}},
+ {Name: "architecture", Values: []string{"amd64"}},
+ }
+
+ result := GetCapabilitiesWithAppliedDefaults(capabilities, capabilityDefinitions)
+
+ Expect(result).To(Equal(Capabilities{
+ "capability1": []string{"value1", "value2"},
+ "architecture": []string{"amd64"},
+ }))
+ })
+
+ It("should retain existing values and apply defaults for missing capabilities", func() {
+ capabilities := Capabilities{
+ "capability1": []string{"value1"},
+ }
+ capabilityDefinitions := []CapabilityDefinition{
+ {Name: "capability1", Values: []string{"value1", "value2"}},
+ {Name: "architecture", Values: []string{"amd64"}},
+ }
+
+ result := GetCapabilitiesWithAppliedDefaults(capabilities, capabilityDefinitions)
+
+ Expect(result).To(Equal(Capabilities{
+ "capability1": []string{"value1"},
+ "architecture": []string{"amd64"},
+ }))
+ })
+ })
})
diff --git a/pkg/apis/core/validation/cloudprofile.go b/pkg/apis/core/validation/cloudprofile.go
index 620dbd35a6a..a8e74025a2d 100644
--- a/pkg/apis/core/validation/cloudprofile.go
+++ b/pkg/apis/core/validation/cloudprofile.go
@@ -56,18 +56,18 @@ func ValidateCloudProfileUpdate(newProfile, oldProfile *core.CloudProfile) field
// ValidateCloudProfileSpec validates the specification of a CloudProfile object.
func ValidateCloudProfileSpec(spec *core.CloudProfileSpec, fldPath *field.Path) field.ErrorList {
var (
- allErrs = field.ErrorList{}
- capabilities = helper.CapabilityDefinitionsToCapabilities(spec.MachineCapabilities)
+ allErrs = field.ErrorList{}
+ machineCapabilities = helper.CapabilityDefinitionsToCapabilities(spec.MachineCapabilities)
)
if len(spec.Type) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("type"), "must provide a provider type"))
}
- allErrs = append(allErrs, validateCloudProfileKubernetesSettings(spec.Kubernetes, fldPath.Child("kubernetes"))...)
- allErrs = append(allErrs, ValidateCloudProfileMachineImages(spec.MachineImages, capabilities, fldPath.Child("machineImages"))...)
- allErrs = append(allErrs, validateCloudProfileMachineTypes(spec.MachineTypes, capabilities, fldPath.Child("machineTypes"))...)
allErrs = append(allErrs, validateCapabilityDefinitions(spec.MachineCapabilities, fldPath.Child("machineCapabilities"))...)
+ allErrs = append(allErrs, validateCloudProfileKubernetesSettings(spec.Kubernetes, fldPath.Child("kubernetes"))...)
+ allErrs = append(allErrs, ValidateCloudProfileMachineImages(spec.MachineImages, machineCapabilities, fldPath.Child("machineImages"))...)
+ allErrs = append(allErrs, validateCloudProfileMachineTypes(spec.MachineTypes, machineCapabilities, fldPath.Child("machineTypes"))...)
allErrs = append(allErrs, validateVolumeTypes(spec.VolumeTypes, fldPath.Child("volumeTypes"))...)
allErrs = append(allErrs, validateCloudProfileRegions(spec.Regions, fldPath.Child("regions"))...)
allErrs = append(allErrs, validateCloudProfileBastion(spec, fldPath.Child("bastion"))...)
@@ -184,23 +184,31 @@ func ValidateCloudProfileMachineImages(machineImages []core.MachineImage, capabi
for index, machineVersion := range image.Versions {
versionsPath := idxPath.Child("versions").Index(index)
- allErrs = append(allErrs, validateContainerRuntimesInterfaces(machineVersion.CRI, versionsPath.Child("cri"))...)
- allErrs = append(allErrs, validateSupportedVersionsConfiguration(machineVersion.ExpirableVersion, helper.ToExpirableVersions(image.Versions), versionsPath)...)
-
- if len(capabilities) == 0 {
- if len(machineVersion.Architectures) == 0 {
- allErrs = append(allErrs, field.Required(versionsPath.Child("architectures"), "must provide at least one architecture"))
- }
- if len(machineVersion.CapabilityFlavors) > 0 {
- allErrs = append(allErrs, field.Forbidden(versionsPath.Child("capabilityFlavors"), "must not provide capabilities without global definition"))
- }
- }
+ allErrs = append(allErrs, ValidateMachineImageAdditionalConfig(machineVersion, versionsPath, image, capabilities)...)
}
}
return allErrs
}
+// ValidateMachineImageAdditionalConfig validates RuntimeInterfaces and supported versions configuration of a MachineImageVersion.
+func ValidateMachineImageAdditionalConfig(machineVersion core.MachineImageVersion, versionsPath *field.Path, image core.MachineImage, capabilities core.Capabilities) field.ErrorList {
+ allErrs := field.ErrorList{}
+
+ allErrs = append(allErrs, validateContainerRuntimesInterfaces(machineVersion.CRI, versionsPath.Child("cri"))...)
+ allErrs = append(allErrs, validateSupportedVersionsConfiguration(machineVersion.ExpirableVersion, helper.ToExpirableVersions(image.Versions), versionsPath)...)
+
+ if len(capabilities) == 0 {
+ if len(machineVersion.Architectures) == 0 {
+ allErrs = append(allErrs, field.Required(versionsPath.Child("architectures"), "must provide at least one architecture"))
+ }
+ if len(machineVersion.CapabilityFlavors) > 0 {
+ allErrs = append(allErrs, field.Forbidden(versionsPath.Child("capabilityFlavors"), "must not provide capabilities without global definition"))
+ }
+ }
+ return allErrs
+}
+
func validateContainerRuntimesInterfaces(cris []core.CRI, fldPath *field.Path) field.ErrorList {
var (
allErrs = field.ErrorList{}
@@ -301,7 +309,7 @@ func validateCloudProfileBastion(spec *core.CloudProfileSpec, fldPath *field.Pat
if spec.Bastion.MachineType != nil {
var validationErrors field.ErrorList
- machineArch, validationErrors = validateBastionMachineType(spec.Bastion.MachineType, spec.MachineTypes, fldPath.Child("machineType"))
+ machineArch, validationErrors = validateBastionMachineType(spec.Bastion.MachineType, spec.MachineTypes, spec.MachineCapabilities, fldPath.Child("machineType"))
allErrs = append(allErrs, validationErrors...)
}
@@ -312,7 +320,7 @@ func validateCloudProfileBastion(spec *core.CloudProfileSpec, fldPath *field.Pat
return allErrs
}
-func validateBastionMachineType(bastionMachineType *core.BastionMachineType, machineTypes []core.MachineType, fldPath *field.Path) (*string, field.ErrorList) {
+func validateBastionMachineType(bastionMachineType *core.BastionMachineType, machineTypes []core.MachineType, capabilityDefinitions []core.CapabilityDefinition, fldPath *field.Path) (*string, field.ErrorList) {
machineIndex := slices.IndexFunc(machineTypes, func(machineType core.MachineType) bool {
return machineType.Name == bastionMachineType.Name
})
@@ -321,7 +329,7 @@ func validateBastionMachineType(bastionMachineType *core.BastionMachineType, mac
return nil, field.ErrorList{field.Invalid(fldPath.Child("name"), bastionMachineType.Name, "machine type not found in spec.machineTypes")}
}
- return ptr.To(machineTypes[machineIndex].GetArchitecture()), nil
+ return ptr.To(machineTypes[machineIndex].GetArchitecture(capabilityDefinitions)), nil
}
func validateBastionImage(bastionImage *core.BastionMachineImage, machineImages []core.MachineImage, capabilities core.Capabilities, machineArch *string, fldPath *field.Path) field.ErrorList {
diff --git a/pkg/apis/core/validation/cloudprofile_test.go b/pkg/apis/core/validation/cloudprofile_test.go
index 21c88498f67..5c69b1ae353 100644
--- a/pkg/apis/core/validation/cloudprofile_test.go
+++ b/pkg/apis/core/validation/cloudprofile_test.go
@@ -1340,11 +1340,51 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
{Name: "architecture", Values: []string{"amd64", "arm64"}},
{Name: "anotherCapability", Values: []string{"value1"}},
}
+ cloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = []core.MachineImageFlavor{
+ {Capabilities: core.Capabilities{"architecture": []string{"amd64"}}},
+ }
+ })
+
+ When("Capability Architecture has one supported value", func() {
+ BeforeEach(func() {
+ cloudProfile.Spec.MachineCapabilities = []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"arm64"}},
+ {Name: "anotherCapability", Values: []string{"value1"}},
+ }
+ })
+
+ It("should succeed to validate with neither architectures nor capabilities set for machine images and types", func() {
+ cloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = nil
+ allErrs := ValidateCloudProfile(cloudProfile)
+ Expect(allErrs).To(BeEmpty())
+ })
})
- It("should succeed to validate with neither architectures nor capability capabilityFlavors set for machine images", func() {
+ It("should succeed to validate with architecture(s) and capabilities set for machine images and types", func() {
cloudProfile.Spec.MachineTypes[0].Architecture = ptr.To("arm64")
- Expect(ValidateCloudProfile(cloudProfile)).To(BeEmpty())
+ cloudProfile.Spec.MachineImages[0].Versions[0].Architectures = []string{"arm64"}
+
+ cloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = []core.MachineImageFlavor{
+ {Capabilities: core.Capabilities{"architecture": []string{"arm64"}}},
+ }
+ cloudProfile.Spec.MachineTypes[0].Capabilities = core.Capabilities{
+ "architecture": []string{"arm64"},
+ }
+ allErrs := ValidateCloudProfile(cloudProfile)
+ Expect(allErrs).To(BeEmpty())
+ })
+
+ It("should fail to validate with machineImages without capabilityFlavors", func() {
+ cloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = nil
+ cloudProfile.Spec.MachineTypes[0].Architecture = ptr.To("arm64")
+
+ Expect(ValidateCloudProfile(cloudProfile)).To(ConsistOf(
+ PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeRequired),
+ "Field": Equal("spec.machineImages[0].versions[0].capabilityFlavors"),
+ "Detail": Equal("must provide at least one image flavor when multiple architectures are defined in spec.machineCapabilities"),
+ })),
+ ))
})
It("should fail to validate with no architecture capability defined in a machine image flavor", func() {
@@ -1357,7 +1397,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeRequired),
"Field": Equal("spec.machineImages[0].versions[0].capabilityFlavors[0].architecture"),
- "Detail": Equal("must provide at least one architecture"),
+ "Detail": Equal("must specify one architecture explicitly as multiple architectures are defined in spec.machineCapabilities"),
})),
))
})
@@ -1371,7 +1411,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.machineImages[0].versions[0].architectures"),
"BadValue": Equal([]string{"arm64"}),
- "Detail": Equal("architecture field values set (arm64) conflict with the capability architectures ()"),
+ "Detail": Equal("architecture field values set (arm64) conflict with the capability architectures (amd64)"),
})),
))
})
@@ -1446,6 +1486,8 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
})
It("should fail to validate capabilities with empty keys or values", func() {
+ cloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = nil
+
cloudProfile.Spec.MachineCapabilities = []core.CapabilityDefinition{
{Name: "", Values: core.CapabilityValues{}},
{Name: "hasNoValues", Values: []string{}},
@@ -1484,7 +1526,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
It("should fail to validate invalid architecture capability values", func() {
cloudProfile.Spec.MachineCapabilities = []core.CapabilityDefinition{
- {Name: "architecture", Values: []string{"arm64", "custom"}},
+ {Name: "architecture", Values: []string{"amd64", "custom"}},
}
Expect(ValidateCloudProfile(cloudProfile)).To(ConsistOf(
@@ -1947,6 +1989,9 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
cloudProfileNew.Spec.MachineCapabilities = []core.CapabilityDefinition{
{Name: "architecture", Values: []string{"amd64", "arm64"}},
}
+ cloudProfileNew.Spec.MachineImages[0].Versions[0].CapabilityFlavors = []core.MachineImageFlavor{
+ {Capabilities: core.Capabilities{"architecture": []string{"amd64"}}},
+ }
if !isInitialSwitch {
cloudProfileOld.Spec.MachineCapabilities = cloudProfileNew.Spec.MachineCapabilities
@@ -1970,7 +2015,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.machineImages[0].versions[0].architectures"),
"BadValue": Equal([]string{"arm64"}),
- "Detail": Equal("architecture field values set (arm64) conflict with the capability architectures ()"),
+ "Detail": Equal("architecture field values set (arm64) conflict with the capability architectures (amd64)"),
})),
))
})
diff --git a/pkg/apis/core/validation/utils.go b/pkg/apis/core/validation/utils.go
index 85a0bf8c966..2adeccc76d8 100644
--- a/pkg/apis/core/validation/utils.go
+++ b/pkg/apis/core/validation/utils.go
@@ -199,63 +199,79 @@ func ValidateMachineImages(machineImages []core.MachineImage, capabilities core.
duplicateName := sets.Set[string]{}
for i, image := range machineImages {
idxPath := fldPath.Index(i)
- if duplicateName.Has(image.Name) {
- allErrs = append(allErrs, field.Duplicate(idxPath, image.Name))
- }
- duplicateName.Insert(image.Name)
+ allErrs = append(allErrs, ValidateMachineImage(image, capabilities, duplicateName, duplicateNameVersion, allowEmptyVersions, idxPath)...)
+ }
- if len(image.Name) == 0 {
- allErrs = append(allErrs, field.Required(idxPath.Child("name"), "machine image name must not be empty"))
- } else if errs := validateUnprefixedQualifiedName(image.Name); len(errs) != 0 {
- allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), image.Name, fmt.Sprintf("machine image name must be a qualified name: %v", errs)))
- }
+ return allErrs
+}
- if len(image.Versions) == 0 && !allowEmptyVersions {
- allErrs = append(allErrs, field.Required(idxPath.Child("versions"), fmt.Sprintf("must provide at least one version for the machine image '%s'", image.Name)))
- }
+// ValidateMachineImage validates a single machine image for valid values and combinations.
+func ValidateMachineImage(image core.MachineImage, capabilities core.Capabilities, duplicateName sets.Set[string], duplicateNameVersion sets.Set[string], allowEmptyVersions bool, idxPath *field.Path) field.ErrorList {
+ allErrs := field.ErrorList{}
- if image.UpdateStrategy != nil {
- if !availableUpdateStrategiesForMachineImage.Has(string(*image.UpdateStrategy)) {
- allErrs = append(allErrs, field.NotSupported(idxPath.Child("updateStrategy"), *image.UpdateStrategy, sets.List(availableUpdateStrategiesForMachineImage)))
- }
- }
+ if duplicateName.Has(image.Name) {
+ allErrs = append(allErrs, field.Duplicate(idxPath, image.Name))
+ }
+ duplicateName.Insert(image.Name)
- for index, machineVersion := range image.Versions {
- versionsPath := idxPath.Child("versions").Index(index)
- key := fmt.Sprintf("%s-%s", image.Name, machineVersion.Version)
- if duplicateNameVersion.Has(key) {
- allErrs = append(allErrs, field.Duplicate(versionsPath, key))
- }
- duplicateNameVersion.Insert(key)
- if len(machineVersion.Version) == 0 {
- allErrs = append(allErrs, field.Required(versionsPath.Child("version"), machineVersion.Version))
- }
+ if len(image.Name) == 0 {
+ allErrs = append(allErrs, field.Required(idxPath.Child("name"), "machine image name must not be empty"))
+ } else if errs := validateUnprefixedQualifiedName(image.Name); len(errs) != 0 {
+ allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), image.Name, fmt.Sprintf("machine image name must be a qualified name: %v", errs)))
+ }
- _, err := semver.NewVersion(machineVersion.Version)
- if err != nil {
- allErrs = append(allErrs, field.Invalid(versionsPath.Child("version"), machineVersion.Version, "could not parse version. Use a semantic version. In case there is no semantic version for this image use the extensibility provider (define mapping in the CloudProfile) to map to the actual non semantic version"))
- }
+ if len(image.Versions) == 0 && !allowEmptyVersions {
+ allErrs = append(allErrs, field.Required(idxPath.Child("versions"), fmt.Sprintf("must provide at least one version for the machine image '%s'", image.Name)))
+ }
- if machineVersion.InPlaceUpdates != nil && machineVersion.InPlaceUpdates.MinVersionForUpdate != nil {
- if _, err = semver.NewVersion(*machineVersion.InPlaceUpdates.MinVersionForUpdate); err != nil {
- allErrs = append(allErrs, field.Invalid(versionsPath.Child("minVersionForInPlaceUpdate"), *machineVersion.InPlaceUpdates.MinVersionForUpdate, "could not parse version. Use a semantic version."))
- }
- }
+ if image.UpdateStrategy != nil {
+ if !availableUpdateStrategiesForMachineImage.Has(string(*image.UpdateStrategy)) {
+ allErrs = append(allErrs, field.NotSupported(idxPath.Child("updateStrategy"), *image.UpdateStrategy, sets.List(availableUpdateStrategiesForMachineImage)))
+ }
+ }
- if machineVersion.Classification != nil && !supportedVersionClassifications.Has(string(*machineVersion.Classification)) {
- allErrs = append(allErrs, field.NotSupported(versionsPath.Child("classification"), *machineVersion.Classification, sets.List(supportedVersionClassifications)))
- }
+ for index, machineVersion := range image.Versions {
+ versionsPath := idxPath.Child("versions").Index(index)
+ allErrs = append(allErrs, ValidateMachineImageVersion(image, machineVersion, capabilities, duplicateNameVersion, versionsPath)...)
+ }
+ return allErrs
+}
- allErrs = append(allErrs, validateMachineImageVersionFlavors(machineVersion, capabilities, versionsPath)...)
+// ValidateMachineImageVersion validates a single machine image version for valid values and combinations.
+func ValidateMachineImageVersion(image core.MachineImage, machineVersion core.MachineImageVersion, capabilities core.Capabilities, duplicateNameVersion sets.Set[string], versionsPath *field.Path) field.ErrorList {
+ allErrs := field.ErrorList{}
- if machineVersion.KubeletVersionConstraint != nil {
- if _, err := semver.NewConstraint(*machineVersion.KubeletVersionConstraint); err != nil {
- allErrs = append(allErrs, field.Invalid(versionsPath.Child("kubeletVersionConstraint"), machineVersion.KubeletVersionConstraint, fmt.Sprintf("cannot parse the kubeletVersionConstraint: %s", err.Error())))
- }
- }
+ key := fmt.Sprintf("%s-%s", image.Name, machineVersion.Version)
+ if duplicateNameVersion.Has(key) {
+ allErrs = append(allErrs, field.Duplicate(versionsPath, key))
+ }
+ duplicateNameVersion.Insert(key)
+ if len(machineVersion.Version) == 0 {
+ allErrs = append(allErrs, field.Required(versionsPath.Child("version"), machineVersion.Version))
+ }
+
+ _, err := semver.NewVersion(machineVersion.Version)
+ if err != nil {
+ allErrs = append(allErrs, field.Invalid(versionsPath.Child("version"), machineVersion.Version, "could not parse version. Use a semantic version. In case there is no semantic version for this image use the extensibility provider (define mapping in the CloudProfile) to map to the actual non semantic version"))
+ }
+
+ if machineVersion.InPlaceUpdates != nil && machineVersion.InPlaceUpdates.MinVersionForUpdate != nil {
+ if _, err = semver.NewVersion(*machineVersion.InPlaceUpdates.MinVersionForUpdate); err != nil {
+ allErrs = append(allErrs, field.Invalid(versionsPath.Child("minVersionForInPlaceUpdate"), *machineVersion.InPlaceUpdates.MinVersionForUpdate, "could not parse version. Use a semantic version."))
}
}
+ if machineVersion.Classification != nil && !supportedVersionClassifications.Has(string(*machineVersion.Classification)) {
+ allErrs = append(allErrs, field.NotSupported(versionsPath.Child("classification"), *machineVersion.Classification, sets.List(supportedVersionClassifications)))
+ }
+
+ allErrs = append(allErrs, validateMachineImageVersionFlavors(machineVersion, capabilities, versionsPath)...)
+
+ if machineVersion.KubeletVersionConstraint != nil {
+ if _, err := semver.NewConstraint(*machineVersion.KubeletVersionConstraint); err != nil {
+ allErrs = append(allErrs, field.Invalid(versionsPath.Child("kubeletVersionConstraint"), machineVersion.KubeletVersionConstraint, fmt.Sprintf("cannot parse the kubeletVersionConstraint: %s", err.Error())))
+ }
+ }
return allErrs
}
@@ -277,33 +293,40 @@ func validateMachineTypes(machineTypes []core.MachineType, capabilities core.Cap
for i, machineType := range machineTypes {
idxPath := fldPath.Index(i)
- namePath := idxPath.Child("name")
- cpuPath := idxPath.Child("cpu")
- gpuPath := idxPath.Child("gpu")
- memoryPath := idxPath.Child("memory")
+ allErrs = append(allErrs, ValidateMachineType(machineType, names, capabilities, idxPath)...)
+ }
- if len(machineType.Name) == 0 {
- allErrs = append(allErrs, field.Required(namePath, "must provide a name"))
- } else if errs := validateUnprefixedQualifiedName(machineType.Name); len(errs) != 0 {
- allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("name"), machineType.Name, fmt.Sprintf("machine type name must be a qualified name: %v", errs)))
- }
+ return allErrs
+}
- if names.Has(machineType.Name) {
- allErrs = append(allErrs, field.Duplicate(namePath, machineType.Name))
- break
- }
- names.Insert(machineType.Name)
+// ValidateMachineType validates a single machine type for valid values and combinations.
+func ValidateMachineType(machineType core.MachineType, names sets.Set[string], capabilities core.Capabilities, idxPath *field.Path) field.ErrorList {
+ allErrs := field.ErrorList{}
- allErrs = append(allErrs, kubernetescorevalidation.ValidateResourceQuantityValue("cpu", machineType.CPU, cpuPath)...)
- allErrs = append(allErrs, kubernetescorevalidation.ValidateResourceQuantityValue("gpu", machineType.GPU, gpuPath)...)
- allErrs = append(allErrs, kubernetescorevalidation.ValidateResourceQuantityValue("memory", machineType.Memory, memoryPath)...)
- allErrs = append(allErrs, validateMachineTypeCapabilities(machineType, capabilities, idxPath)...)
+ namePath := idxPath.Child("name")
+ cpuPath := idxPath.Child("cpu")
+ gpuPath := idxPath.Child("gpu")
+ memoryPath := idxPath.Child("memory")
- if machineType.Storage != nil {
- allErrs = append(allErrs, validateMachineTypeStorage(*machineType.Storage, idxPath.Child("storage"))...)
- }
+ if len(machineType.Name) == 0 {
+ allErrs = append(allErrs, field.Required(namePath, "must provide a name"))
+ } else if errs := validateUnprefixedQualifiedName(machineType.Name); len(errs) != 0 {
+ allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), machineType.Name, fmt.Sprintf("machine type name must be a qualified name: %v", errs)))
+ }
+
+ if names.Has(machineType.Name) {
+ return append(allErrs, field.Duplicate(namePath, machineType.Name))
}
+ names.Insert(machineType.Name)
+ allErrs = append(allErrs, kubernetescorevalidation.ValidateResourceQuantityValue("cpu", machineType.CPU, cpuPath)...)
+ allErrs = append(allErrs, kubernetescorevalidation.ValidateResourceQuantityValue("gpu", machineType.GPU, gpuPath)...)
+ allErrs = append(allErrs, kubernetescorevalidation.ValidateResourceQuantityValue("memory", machineType.Memory, memoryPath)...)
+ allErrs = append(allErrs, validateMachineTypeCapabilities(machineType, capabilities, idxPath)...)
+
+ if machineType.Storage != nil {
+ allErrs = append(allErrs, validateMachineTypeStorage(*machineType.Storage, idxPath.Child("storage"))...)
+ }
return allErrs
}
@@ -379,25 +402,35 @@ func validateMachineImageVersionArchitecture(machineImageVersion core.MachineIma
// assert that the architecture values defined do not conflict
if len(capabilities) > 0 {
supportedArchitectures = capabilities[v1beta1constants.ArchitectureName]
+
+ if len(supportedArchitectures) > 1 && len(machineImageVersion.CapabilityFlavors) == 0 {
+ return append(allErrs, field.Required(fldPath.Child("capabilityFlavors"),
+ "must provide at least one image flavor when multiple architectures are defined in spec.machineCapabilities"))
+ }
+
for flavorIdx, flavor := range machineImageVersion.CapabilityFlavors {
architectureCapabilityValues := flavor.Capabilities[v1beta1constants.ArchitectureName]
architectureFieldPath := fldPath.Child("capabilityFlavors").Index(flavorIdx).Child("architecture")
- if len(architectureCapabilityValues) == 0 {
- allErrs = append(allErrs, field.Required(architectureFieldPath, "must provide at least one architecture"))
+ if len(architectureCapabilityValues) == 0 && len(supportedArchitectures) > 1 {
+ allErrs = append(allErrs, field.Required(architectureFieldPath, "must specify one architecture explicitly as multiple architectures are defined in spec.machineCapabilities"))
} else if len(architectureCapabilityValues) > 1 {
allErrs = append(allErrs, field.Invalid(architectureFieldPath, architectureCapabilityValues, "must not define more than one architecture within an image flavor"))
}
}
allCapabilityArchitectures := sets.New(gardencorehelper.ExtractArchitecturesFromImageFlavors(machineImageVersion.CapabilityFlavors)...)
+ if len(allCapabilityArchitectures) == 0 && len(supportedArchitectures) == 1 {
+ allCapabilityArchitectures = sets.New(supportedArchitectures...)
+ }
if len(machineImageVersion.Architectures) > 0 && !allCapabilityArchitectures.HasAll(machineImageVersion.Architectures...) {
- allErrs = append(allErrs, field.Invalid(fldPath.Child("architectures"), machineImageVersion.Architectures, fmt.Sprintf("architecture field values set (%s) conflict with the capability architectures (%s)", strings.Join(machineImageVersion.Architectures, ","), strings.Join(allCapabilityArchitectures.UnsortedList(), ","))))
+ allErrs = append(allErrs, field.Invalid(fldPath.Child("architectures"), machineImageVersion.Architectures,
+ fmt.Sprintf("architecture field values set (%s) conflict with the capability architectures (%s)", strings.Join(machineImageVersion.Architectures, ","), strings.Join(allCapabilityArchitectures.UnsortedList(), ","))))
}
}
for archIdx, arch := range machineImageVersion.Architectures {
if !slices.Contains(supportedArchitectures, arch) {
- allErrs = append(allErrs, field.NotSupported(fldPath.Child("architectures").Index(archIdx), arch, v1beta1constants.ValidArchitectures))
+ allErrs = append(allErrs, field.NotSupported(fldPath.Child("architectures").Index(archIdx), arch, supportedArchitectures))
}
}
diff --git a/pkg/apiserver/registry/core/cloudprofile/strategy_test.go b/pkg/apiserver/registry/core/cloudprofile/strategy_test.go
index de3717ba878..f78b177fee1 100644
--- a/pkg/apiserver/registry/core/cloudprofile/strategy_test.go
+++ b/pkg/apiserver/registry/core/cloudprofile/strategy_test.go
@@ -186,7 +186,7 @@ var _ = Describe("Strategy", func() {
}
newCloudProfile := oldCloudProfile.DeepCopy()
newCloudProfile.Spec.MachineCapabilities = []core.CapabilityDefinition{
- {Name: "architecture", Values: []string{"amd64"}},
+ {Name: "architecture", Values: []string{"amd64", "arm64"}},
}
cloudprofileregistry.Strategy.PrepareForUpdate(context.Background(), newCloudProfile, oldCloudProfile)
@@ -200,7 +200,6 @@ var _ = Describe("Strategy", func() {
}))
})
})
-
Describe("#Canonicalize", func() {
It("should sync architecture capabilities to empty architecture fields", func() {
cloudProfile := &core.CloudProfile{
diff --git a/pkg/controllermanager/controller/namespacedcloudprofile/reconciler.go b/pkg/controllermanager/controller/namespacedcloudprofile/reconciler.go
index b7b5fde79bf..edc129dfc77 100644
--- a/pkg/controllermanager/controller/namespacedcloudprofile/reconciler.go
+++ b/pkg/controllermanager/controller/namespacedcloudprofile/reconciler.go
@@ -21,6 +21,7 @@ import (
"github.com/gardener/gardener/pkg/api"
gardencore "github.com/gardener/gardener/pkg/apis/core"
+ gardencorehelper "github.com/gardener/gardener/pkg/apis/core/helper"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
@@ -118,8 +119,11 @@ func MergeCloudProfiles(namespacedCloudProfile *gardencorev1beta1.NamespacedClou
if namespacedCloudProfile.Spec.Kubernetes != nil {
namespacedCloudProfile.Status.CloudProfileSpec.Kubernetes.Versions = mergeDeep(namespacedCloudProfile.Status.CloudProfileSpec.Kubernetes.Versions, namespacedCloudProfile.Spec.Kubernetes.Versions, expirableVersionKeyFunc, mergeExpirationDates, false)
}
- namespacedCloudProfile.Status.CloudProfileSpec.MachineImages = mergeDeep(namespacedCloudProfile.Status.CloudProfileSpec.MachineImages, namespacedCloudProfile.Spec.MachineImages, machineImageKeyFunc, mergeMachineImages, true)
- namespacedCloudProfile.Status.CloudProfileSpec.MachineTypes = mergeDeep(namespacedCloudProfile.Status.CloudProfileSpec.MachineTypes, namespacedCloudProfile.Spec.MachineTypes, machineTypeKeyFunc, nil, true)
+
+ // TODO(Roncossek): Remove TransformSpecToParentFormat once all CloudProfiles have been migrated to use CapabilityFlavors and the Architecture fields are effectively forbidden or have been removed.
+ uniformNamespacedCloudProfileSpec := gardenerutils.TransformSpecToParentFormat(namespacedCloudProfile.Spec, cloudProfile.Spec.MachineCapabilities)
+ namespacedCloudProfile.Status.CloudProfileSpec.MachineImages = mergeDeep(namespacedCloudProfile.Status.CloudProfileSpec.MachineImages, uniformNamespacedCloudProfileSpec.MachineImages, machineImageKeyFunc, mergeMachineImages, true)
+ namespacedCloudProfile.Status.CloudProfileSpec.MachineTypes = mergeDeep(namespacedCloudProfile.Status.CloudProfileSpec.MachineTypes, uniformNamespacedCloudProfileSpec.MachineTypes, machineTypeKeyFunc, nil, true)
namespacedCloudProfile.Status.CloudProfileSpec.VolumeTypes = mergeDeep(namespacedCloudProfile.Status.CloudProfileSpec.VolumeTypes, namespacedCloudProfile.Spec.VolumeTypes, volumeTypeKeyFunc, nil, true)
if namespacedCloudProfile.Spec.CABundle != nil {
mergedCABundles := fmt.Sprintf("%s%s", ptr.Deref(namespacedCloudProfile.Status.CloudProfileSpec.CABundle, ""), ptr.Deref(namespacedCloudProfile.Spec.CABundle, ""))
@@ -140,17 +144,39 @@ func MergeCloudProfiles(namespacedCloudProfile *gardencorev1beta1.NamespacedClou
func syncArchitectureCapabilities(namespacedCloudProfile *gardencorev1beta1.NamespacedCloudProfile) {
var coreCloudProfileSpec gardencore.CloudProfileSpec
_ = api.Scheme.Convert(&namespacedCloudProfile.Status.CloudProfileSpec, &coreCloudProfileSpec, nil)
- gardenerutils.SyncArchitectureCapabilityFields(coreCloudProfileSpec, gardencore.CloudProfileSpec{})
- defaultMachineTypeArchitectures(coreCloudProfileSpec)
+ defaultMachineTypeArchitectures(coreCloudProfileSpec, coreCloudProfileSpec.MachineCapabilities)
+ defaultMachineImageArchitectures(coreCloudProfileSpec, coreCloudProfileSpec.MachineCapabilities)
_ = api.Scheme.Convert(&coreCloudProfileSpec, &namespacedCloudProfile.Status.CloudProfileSpec, nil)
}
// defaultMachineTypeArchitectures defaults the architectures of the machine types for NamespacedCloudProfiles.
// The sync can only happen after having had a look at the parent CloudProfile and whether it uses capabilities.
-func defaultMachineTypeArchitectures(cloudProfile gardencore.CloudProfileSpec) {
+func defaultMachineTypeArchitectures(cloudProfile gardencore.CloudProfileSpec, capabilitiesDefinitions []gardencore.CapabilityDefinition) {
for i, machineType := range cloudProfile.MachineTypes {
- if machineType.GetArchitecture() == "" {
+ effectiveArchitecture := machineType.GetArchitecture(capabilitiesDefinitions)
+ if effectiveArchitecture == "" {
cloudProfile.MachineTypes[i].Architecture = ptr.To(v1beta1constants.ArchitectureAMD64)
+ } else if cloudProfile.MachineTypes[i].Architecture == nil {
+ cloudProfile.MachineTypes[i].Architecture = ptr.To(effectiveArchitecture)
+ }
+ }
+}
+
+// defaultMachineImageArchitectures defaults the architectures of the machine images for NamespacedCloudProfiles.
+// The sync can only happen after having had a look at the parent CloudProfile and whether it uses capabilities.
+func defaultMachineImageArchitectures(cloudProfile gardencore.CloudProfileSpec, capabilitiesDefinitions []gardencore.CapabilityDefinition) {
+ for i, machineImage := range cloudProfile.MachineImages {
+ for j, version := range machineImage.Versions {
+ if len(version.Architectures) > 0 {
+ continue
+ }
+ capabilityFlavors := gardencorehelper.GetImageFlavorsWithAppliedDefaults(version.CapabilityFlavors, capabilitiesDefinitions)
+ capabilityArchitectures := gardencorehelper.ExtractArchitecturesFromImageFlavors(capabilityFlavors)
+ if len(capabilityArchitectures) == 0 {
+ cloudProfile.MachineImages[i].Versions[j].Architectures = []string{v1beta1constants.ArchitectureAMD64}
+ } else if len(capabilityArchitectures) > 0 {
+ cloudProfile.MachineImages[i].Versions[j].Architectures = capabilityArchitectures
+ }
}
}
}
diff --git a/pkg/controllermanager/controller/namespacedcloudprofile/reconciler_test.go b/pkg/controllermanager/controller/namespacedcloudprofile/reconciler_test.go
index 2e56f27c1db..786d8ab300b 100644
--- a/pkg/controllermanager/controller/namespacedcloudprofile/reconciler_test.go
+++ b/pkg/controllermanager/controller/namespacedcloudprofile/reconciler_test.go
@@ -12,6 +12,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gstruct"
"go.uber.org/mock/gomock"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
@@ -531,7 +532,7 @@ var _ = Describe("NamespacedCloudProfile Reconciler", func() {
c.EXPECT().Status().Return(sw),
sw.EXPECT().Patch(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.NamespacedCloudProfile{}), gomock.Any()).DoAndReturn(func(_ context.Context, o client.Object, patch client.Patch, _ ...client.PatchOption) error {
versionOverride := fmt.Sprintf(`{"architectures":["amd64"],"cri":[{"name":"containerd"}],"expirationDate":"%s","kubeletVersionConstraint":"==1.30.0","version":"1.0.0"}`, newExpiryDate.UTC().Format(time.RFC3339))
- versionAdded := `{"version":"1.1.2"}`
+ versionAdded := `{"architectures":["amd64"],"version":"1.1.2"}`
Expect(patch.Data(o)).To(And(
// The order is (currently) indeterministic.
ContainSubstring(`{"status":{"cloudProfileSpec":{"machineImages":[{"name":"test-image","updateStrategy":"major","versions":[`),
@@ -755,10 +756,16 @@ var _ = Describe("NamespacedCloudProfile Reconciler", func() {
Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(namespacedCloudProfile), namespacedCloudProfile)).To(Succeed())
Expect(namespacedCloudProfile.Status.CloudProfileSpec.MachineImages).To(ConsistOf(
gardencorev1beta1.MachineImage{Name: "machine-image-1", Versions: []gardencorev1beta1.MachineImageVersion{
- {ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "1.0.0"}},
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "1.0.0"},
+ Architectures: []string{"amd64"},
+ },
}},
gardencorev1beta1.MachineImage{Name: "machine-image-2", Versions: []gardencorev1beta1.MachineImageVersion{
- {ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "2.0.0"}},
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "2.0.0"},
+ Architectures: []string{"amd64"},
+ },
}},
))
Expect(namespacedCloudProfile.Status.CloudProfileSpec.ProviderConfig.Raw).To(Equal(
@@ -803,10 +810,16 @@ var _ = Describe("NamespacedCloudProfile Reconciler", func() {
Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(namespacedCloudProfile), namespacedCloudProfile)).To(Succeed())
Expect(namespacedCloudProfile.Status.CloudProfileSpec.MachineImages).To(ConsistOf(
gardencorev1beta1.MachineImage{Name: "machine-image-1", Versions: []gardencorev1beta1.MachineImageVersion{
- {ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "1.0.0"}},
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "1.0.0"},
+ Architectures: []string{"amd64"},
+ },
}},
gardencorev1beta1.MachineImage{Name: "machine-image-2", Versions: []gardencorev1beta1.MachineImageVersion{
- {ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "3.0.0"}},
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "3.0.0"},
+ Architectures: []string{"amd64"},
+ },
}},
))
// Make sure that status providerConfig is set to cloudProfile providerConfig again.
@@ -908,6 +921,250 @@ var _ = Describe("NamespacedCloudProfile Reconciler", func() {
Expect(namespacedCloudProfile.Status.CloudProfileSpec.Limits.MaxNodesTotal).To(Equal(ptr.To(int32(20))))
})
})
+
+ Describe("Transform to parent CloudProfile capability/legacy format functionality", func() {
+ var (
+ cloudProfile *gardencorev1beta1.CloudProfile
+ namespacedCloudProfile *gardencorev1beta1.NamespacedCloudProfile
+ )
+
+ BeforeEach(func() {
+ cloudProfile = &gardencorev1beta1.CloudProfile{}
+ namespacedCloudProfile = &gardencorev1beta1.NamespacedCloudProfile{}
+ })
+
+ When("parent CloudProfile has capability definitions", func() {
+ BeforeEach(func() {
+ cloudProfile.Spec.MachineCapabilities = []gardencorev1beta1.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"amd64", "arm64"}},
+ }
+ })
+
+ It("should transform legacy architectures to capability flavors when parent is in capability format", func() {
+ namespacedCloudProfile.Spec.MachineImages = []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "20.04"},
+ Architectures: []string{"amd64", "arm64"},
+ },
+ },
+ },
+ }
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ Expect(namespacedCloudProfile.Status.CloudProfileSpec.MachineImages).To(HaveLen(1))
+ Expect(namespacedCloudProfile.Status.CloudProfileSpec.MachineImages[0].Versions).To(HaveLen(1))
+ version := namespacedCloudProfile.Status.CloudProfileSpec.MachineImages[0].Versions[0]
+ Expect(version.CapabilityFlavors).To(HaveLen(2))
+ Expect(version.CapabilityFlavors[0].Capabilities).To(HaveKeyWithValue("architecture", gardencorev1beta1.CapabilityValues{"amd64"}))
+ Expect(version.CapabilityFlavors[1].Capabilities).To(HaveKeyWithValue("architecture", gardencorev1beta1.CapabilityValues{"arm64"}))
+ Expect(version.Architectures).To(ConsistOf("amd64", "arm64"))
+ })
+
+ It("should add architecture to capabilityFlavors", func() {
+ namespacedCloudProfile.Spec.MachineImages = []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "20.04"},
+ Architectures: []string{"amd64"},
+ },
+ },
+ },
+ }
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ version := namespacedCloudProfile.Status.CloudProfileSpec.MachineImages[0].Versions[0]
+ Expect(version.CapabilityFlavors).To(HaveLen(1))
+ Expect(version.CapabilityFlavors[0].Capabilities).To(HaveKeyWithValue("architecture", gardencorev1beta1.CapabilityValues{"amd64"}))
+ Expect(version.Architectures).To(ConsistOf("amd64"))
+ })
+
+ It("should preserve existing capability flavors", func() {
+ namespacedCloudProfile.Spec.MachineImages = []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "20.04"},
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": []string{"arm64"},
+ "gpu": []string{"nvidia"},
+ },
+ },
+ },
+ Architectures: []string{"arm64"},
+ },
+ },
+ },
+ }
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ version := namespacedCloudProfile.Status.CloudProfileSpec.MachineImages[0].Versions[0]
+ Expect(version.CapabilityFlavors).To(HaveLen(1))
+ Expect(version.CapabilityFlavors[0].Capabilities).To(HaveKeyWithValue("architecture", gardencorev1beta1.CapabilityValues{"arm64"}))
+ Expect(version.CapabilityFlavors[0].Capabilities).To(HaveKeyWithValue("gpu", gardencorev1beta1.CapabilityValues{"nvidia"}))
+ })
+
+ It("should set architecture capabilities for machine types", func() {
+ namespacedCloudProfile.Spec.MachineTypes = []gardencorev1beta1.MachineType{
+ {
+ Name: "m5.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ },
+ {
+ Name: "m5.arm.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ Architecture: ptr.To("arm64"),
+ },
+ }
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ machineTypes := namespacedCloudProfile.Status.CloudProfileSpec.MachineTypes
+ Expect(machineTypes).To(HaveLen(2))
+
+ Expect(machineTypes).To(ConsistOf(
+ MatchFields(IgnoreExtras, Fields{
+ "Architecture": Equal(ptr.To("amd64")),
+ "Capabilities": HaveKeyWithValue("architecture", gardencorev1beta1.CapabilityValues{"amd64"}),
+ }),
+ MatchFields(IgnoreExtras, Fields{
+ "Architecture": Equal(ptr.To("arm64")),
+ "Capabilities": HaveKeyWithValue("architecture", gardencorev1beta1.CapabilityValues{"arm64"}),
+ }),
+ ))
+ })
+ })
+
+ When("parent CloudProfile has no capability definitions", func() {
+ BeforeEach(func() {
+ cloudProfile.Spec.MachineCapabilities = nil
+ })
+
+ It("should preserve existing architectures", func() {
+ namespacedCloudProfile.Spec.MachineImages = []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "20.04"},
+ Architectures: []string{"amd64", "arm64"},
+ },
+ },
+ },
+ }
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ version := namespacedCloudProfile.Status.CloudProfileSpec.MachineImages[0].Versions[0]
+ Expect(version.Architectures).To(ConsistOf("amd64", "arm64"))
+ Expect(version.CapabilityFlavors).To(BeNil())
+ })
+
+ It("should clear capabilities for machine types", func() {
+ namespacedCloudProfile.Spec.MachineTypes = []gardencorev1beta1.MachineType{
+ {
+ Name: "m5.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": []string{"amd64"},
+ "gpu": []string{"nvidia"},
+ },
+ },
+ }
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ machineType := namespacedCloudProfile.Status.CloudProfileSpec.MachineTypes[0]
+ Expect(machineType.Architecture).To(Equal(ptr.To("amd64")))
+ Expect(machineType.Capabilities).To(BeNil())
+ })
+
+ It("should handle multiple capability flavors with different architectures", func() {
+ namespacedCloudProfile.Spec.MachineImages = []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "20.04"},
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": []string{"amd64"},
+ },
+ },
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": []string{"arm64"},
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ version := namespacedCloudProfile.Status.CloudProfileSpec.MachineImages[0].Versions[0]
+ Expect(version.Architectures).To(ConsistOf("amd64", "arm64"))
+ Expect(version.CapabilityFlavors).To(BeNil())
+ })
+ })
+
+ Context("edge cases", func() {
+ It("should handle empty machine images list", func() {
+ namespacedCloudProfile.Spec.MachineImages = []gardencorev1beta1.MachineImage{}
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ Expect(namespacedCloudProfile.Status.CloudProfileSpec.MachineImages).To(BeEmpty())
+ })
+
+ It("should handle empty machine types list", func() {
+ namespacedCloudProfile.Spec.MachineTypes = []gardencorev1beta1.MachineType{}
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ Expect(namespacedCloudProfile.Status.CloudProfileSpec.MachineTypes).To(BeEmpty())
+ })
+
+ It("should handle machine image versions with no architectures and no capability flavors", func() {
+ cloudProfile.Spec.MachineCapabilities = []gardencorev1beta1.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"amd64"}},
+ }
+ namespacedCloudProfile.Spec.MachineImages = []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "20.04"},
+ },
+ },
+ },
+ }
+
+ namespacedcloudprofilecontroller.MergeCloudProfiles(namespacedCloudProfile, cloudProfile)
+
+ version := namespacedCloudProfile.Status.CloudProfileSpec.MachineImages[0].Versions[0]
+ // no architectures specified so should default to amd64 as per parent capability definition
+ Expect(version.CapabilityFlavors).To(BeEmpty())
+ Expect(version.Architectures).To(ConsistOf("amd64"))
+ })
+ })
+ })
})
})
})
diff --git a/pkg/provider-local/admission/mutator/namespacedcloudprofile.go b/pkg/provider-local/admission/mutator/namespacedcloudprofile.go
index f20ba7f7822..afd3c5e656f 100644
--- a/pkg/provider-local/admission/mutator/namespacedcloudprofile.go
+++ b/pkg/provider-local/admission/mutator/namespacedcloudprofile.go
@@ -57,7 +57,10 @@ func (p *namespacedCloudProfile) Mutate(_ context.Context, newObj, _ client.Obje
return fmt.Errorf("could not decode providerConfig of namespacedCloudProfile status for '%s': %w", profile.Name, err)
}
- statusConfig.MachineImages = mergeMachineImages(specConfig.MachineImages, statusConfig.MachineImages)
+ // TODO(Roncossek): Remove TransformProviderConfigToParentFormat once all CloudProfiles have been migrated to use CapabilityFlavors and the Architecture fields are effectively forbidden or have been removed.
+ uniformSpecConfig := TransformProviderConfigToParentFormat(specConfig, profile.Status.CloudProfileSpec.MachineCapabilities)
+
+ statusConfig.MachineImages = mergeMachineImages(uniformSpecConfig.MachineImages, statusConfig.MachineImages)
modifiedStatusConfig, err := json.Marshal(statusConfig)
if err != nil {
@@ -68,6 +71,32 @@ func (p *namespacedCloudProfile) Mutate(_ context.Context, newObj, _ client.Obje
return nil
}
+// TransformProviderConfigToParentFormat supports the migration from the deprecated architecture fields to architecture capabilities during a transition period.
+// Depending on whether the parent CloudProfile is in capability format or not, it transforms the given config to
+// the capability format or the deprecated architecture fields format respectively.
+// It assumes that the given config is either completely in the capability format or in the deprecated architecture fields format.
+func TransformProviderConfigToParentFormat(cloudProfileConfig *v1alpha1.CloudProfileConfig, capabilityDefinitions []gardencorev1beta1.CapabilityDefinition) *v1alpha1.CloudProfileConfig {
+ isParentInCapabilityFormat := len(capabilityDefinitions) != 0
+ for idx, machineImage := range cloudProfileConfig.MachineImages {
+ cloudProfileConfig.MachineImages[idx].Versions = make([]v1alpha1.MachineImageVersion, 0, len(machineImage.Versions))
+ for _, version := range machineImage.Versions {
+ isVersionInCapabilityFormat := len(version.CapabilityFlavors) != 0
+ transformedVersion := v1alpha1.MachineImageVersion{Version: version.Version}
+ if isParentInCapabilityFormat && !isVersionInCapabilityFormat {
+ // transform to capability format
+ transformedVersion.CapabilityFlavors = []v1alpha1.MachineImageFlavor{{Image: version.Image}}
+ } else if !isParentInCapabilityFormat && isVersionInCapabilityFormat {
+ // transform to old format
+ transformedVersion.Image = version.CapabilityFlavors[0].Image
+ } else {
+ transformedVersion = version
+ }
+ cloudProfileConfig.MachineImages[idx].Versions = append(cloudProfileConfig.MachineImages[idx].Versions, transformedVersion)
+ }
+ }
+ return cloudProfileConfig
+}
+
func mergeMachineImages(specMachineImages, statusMachineImages []v1alpha1.MachineImages) []v1alpha1.MachineImages {
specImages := utils.CreateMapFromSlice(specMachineImages, func(mi v1alpha1.MachineImages) string { return mi.Name })
statusImages := utils.CreateMapFromSlice(statusMachineImages, func(mi v1alpha1.MachineImages) string { return mi.Name })
diff --git a/pkg/provider-local/admission/mutator/namespacedcloudprofile_test.go b/pkg/provider-local/admission/mutator/namespacedcloudprofile_test.go
index 475275ba592..f5184874816 100644
--- a/pkg/provider-local/admission/mutator/namespacedcloudprofile_test.go
+++ b/pkg/provider-local/admission/mutator/namespacedcloudprofile_test.go
@@ -21,10 +21,11 @@ import (
"github.com/gardener/gardener/extensions/pkg/util"
extensionswebhook "github.com/gardener/gardener/extensions/pkg/webhook"
- "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/provider-local/admission/mutator"
api "github.com/gardener/gardener/pkg/provider-local/apis/local"
"github.com/gardener/gardener/pkg/provider-local/apis/local/install"
+ "github.com/gardener/gardener/pkg/provider-local/apis/local/v1alpha1"
"github.com/gardener/gardener/pkg/utils/test"
. "github.com/gardener/gardener/pkg/utils/test/matchers"
)
@@ -38,13 +39,13 @@ var _ = Describe("NamespacedCloudProfile Mutator", func() {
decoder runtime.Decoder
namespacedCloudProfileMutator extensionswebhook.Mutator
- namespacedCloudProfile *v1beta1.NamespacedCloudProfile
+ namespacedCloudProfile *gardencorev1beta1.NamespacedCloudProfile
)
BeforeEach(func() {
scheme := runtime.NewScheme()
utilruntime.Must(install.AddToScheme(scheme))
- utilruntime.Must(v1beta1.AddToScheme(scheme))
+ utilruntime.Must(gardencorev1beta1.AddToScheme(scheme))
fakeClient = fakeclient.NewClientBuilder().WithScheme(scheme).Build()
fakeManager = &test.FakeManager{
Client: fakeClient,
@@ -54,7 +55,7 @@ var _ = Describe("NamespacedCloudProfile Mutator", func() {
decoder = serializer.NewCodecFactory(fakeManager.GetScheme(), serializer.EnableStrict).UniversalDecoder()
namespacedCloudProfileMutator = mutator.NewNamespacedCloudProfileMutator(fakeManager)
- namespacedCloudProfile = &v1beta1.NamespacedCloudProfile{
+ namespacedCloudProfile = &gardencorev1beta1.NamespacedCloudProfile{
ObjectMeta: metav1.ObjectMeta{
Name: "profile-1",
Namespace: namespace,
@@ -62,6 +63,81 @@ var _ = Describe("NamespacedCloudProfile Mutator", func() {
}
})
+ Describe("TransformProviderConfigToParentFormat", func() {
+ var parentCloudProfile *gardencorev1beta1.CloudProfile
+ var cpConfig *v1alpha1.CloudProfileConfig
+ var capabilityMachineImage v1alpha1.MachineImages
+ var legacyMachineImage v1alpha1.MachineImages
+
+ BeforeEach(func() {
+ parentCloudProfile = &gardencorev1beta1.CloudProfile{
+ Spec: gardencorev1beta1.CloudProfileSpec{},
+ }
+ cpConfig = &v1alpha1.CloudProfileConfig{
+ TypeMeta: metav1.TypeMeta{
+ Kind: "CloudProfileConfig",
+ APIVersion: "local.provider.extensions.gardener.cloud/v1alpha1",
+ },
+ }
+ capabilityMachineImage = v1alpha1.MachineImages{
+ Name: "image-1",
+ Versions: []v1alpha1.MachineImageVersion{{
+ Version: "1.0",
+ CapabilityFlavors: []v1alpha1.MachineImageFlavor{{
+ Image: "local/image:1.0-amd64",
+ }},
+ }},
+ }
+ legacyMachineImage = v1alpha1.MachineImages{
+ Name: "image-1",
+ Versions: []v1alpha1.MachineImageVersion{{
+ Version: "1.0",
+ Image: "local/image:1.0-amd64",
+ }},
+ }
+ })
+
+ When("the parent CloudProfile has machineCapabilities defined", func() {
+ BeforeEach(func() {
+ parentCloudProfile.Spec.MachineCapabilities = []gardencorev1beta1.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"amd64", "arm64"}},
+ }
+ })
+
+ It("should do nothing if the NamespacedCloudProfile spec is in capability format", func() {
+ machineImages := []v1alpha1.MachineImages{capabilityMachineImage}
+ cpConfig.MachineImages = machineImages
+
+ uniformSpecConfig := mutator.TransformProviderConfigToParentFormat(cpConfig, parentCloudProfile.Spec.MachineCapabilities)
+ Expect(uniformSpecConfig.MachineImages).To(ContainElements(machineImages))
+ Expect(uniformSpecConfig).To(BeEquivalentTo(cpConfig))
+ })
+
+ It("should transform the status to capability format if the NamespacedCloudProfile spec is in old format", func() {
+ cpConfig.MachineImages = []v1alpha1.MachineImages{legacyMachineImage}
+ uniformSpecConfig := mutator.TransformProviderConfigToParentFormat(cpConfig, parentCloudProfile.Spec.MachineCapabilities)
+ Expect(uniformSpecConfig.MachineImages[0]).To(Equal(capabilityMachineImage))
+ })
+ })
+
+ When("the parentCloudProfile has NO machineCapabilities defined", func() {
+ It("should do nothing if the NamespacedCloudProfile spec is in legacy format", func() {
+ machineImages := []v1alpha1.MachineImages{legacyMachineImage}
+ cpConfig.MachineImages = machineImages
+
+ uniformSpecConfig := mutator.TransformProviderConfigToParentFormat(cpConfig, parentCloudProfile.Spec.MachineCapabilities)
+ Expect(uniformSpecConfig.MachineImages).To(ContainElements(machineImages))
+ Expect(uniformSpecConfig).To(BeEquivalentTo(cpConfig))
+ })
+
+ It("should transform the status to legacy format if the NamespacedCloudProfile spec is in capability format", func() {
+ cpConfig.MachineImages = []v1alpha1.MachineImages{capabilityMachineImage}
+ uniformSpecConfig := mutator.TransformProviderConfigToParentFormat(cpConfig, parentCloudProfile.Spec.MachineCapabilities)
+ Expect(uniformSpecConfig.MachineImages[0]).To(Equal(legacyMachineImage))
+ })
+ })
+ })
+
Describe("#Mutate", func() {
It("should succeed for NamespacedCloudProfile without provider config", func() {
Expect(namespacedCloudProfileMutator.Mutate(ctx, namespacedCloudProfile, nil)).To(Succeed())
diff --git a/pkg/provider-local/admission/validator/cloudprofile.go b/pkg/provider-local/admission/validator/cloudprofile.go
index 692dd3a2f90..91c0d1af6bb 100644
--- a/pkg/provider-local/admission/validator/cloudprofile.go
+++ b/pkg/provider-local/admission/validator/cloudprofile.go
@@ -48,9 +48,11 @@ func (cp *cloudProfileValidator) Validate(_ context.Context, newObj, _ client.Ob
if err != nil {
return fmt.Errorf("could not decode providerConfig of CloudProfile %q: %w", cloudProfile.Name, err)
}
- CapabilityDefinition, err := helper.ConvertV1beta1CapabilityDefinitions(cloudProfile.Spec.MachineCapabilities)
+
+ capabilityDefinitions, err := helper.ConvertV1beta1CapabilityDefinitions(cloudProfile.Spec.MachineCapabilities)
if err != nil {
return field.InternalError(field.NewPath("spec").Child("machineCapabilities"), err)
}
- return validation.ValidateCloudProfileConfig(cpConfig, cloudProfile.Spec.MachineImages, CapabilityDefinition, providerConfigPath).ToAggregate()
+
+ return validation.ValidateCloudProfileConfig(cpConfig, cloudProfile.Spec.MachineImages, capabilityDefinitions, providerConfigPath).ToAggregate()
}
diff --git a/pkg/provider-local/admission/validator/namespacedcloudprofile.go b/pkg/provider-local/admission/validator/namespacedcloudprofile.go
index a5c4afcef0c..781a562da85 100644
--- a/pkg/provider-local/admission/validator/namespacedcloudprofile.go
+++ b/pkg/provider-local/admission/validator/namespacedcloudprofile.go
@@ -15,11 +15,15 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
extensionswebhook "github.com/gardener/gardener/extensions/pkg/webhook"
+ gardencoreapi "github.com/gardener/gardener/pkg/api"
"github.com/gardener/gardener/pkg/apis/core"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
"github.com/gardener/gardener/pkg/provider-local/admission"
+ "github.com/gardener/gardener/pkg/provider-local/admission/mutator"
api "github.com/gardener/gardener/pkg/provider-local/apis/local"
+ "github.com/gardener/gardener/pkg/provider-local/apis/local/helper"
+ "github.com/gardener/gardener/pkg/provider-local/apis/local/v1alpha1"
"github.com/gardener/gardener/pkg/provider-local/apis/local/validation"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
)
@@ -66,6 +70,10 @@ func (p *namespacedCloudProfileValidator) Validate(ctx context.Context, new, _ c
return err
}
+ if err := SimulateTransformToParentFormat(cloudProfileConfig, cloudProfile, parentProfile.Spec.MachineCapabilities); err != nil {
+ return err
+ }
+
return p.validateNamespacedCloudProfileProviderConfig(cloudProfileConfig, cloudProfile.Spec.MachineImages, parentProfile).ToAggregate()
}
@@ -130,3 +138,32 @@ func (p *namespacedCloudProfileValidator) validateNamespacedCloudProfileProvider
return allErrs
}
+
+// SimulateTransformToParentFormat simulates the transformation of the given NamespacedCloudProfile and its providerConfig
+// to the parent CloudProfile format. This includes the transformation of both the providerConfig and the spec.
+func SimulateTransformToParentFormat(cloudProfileConfig *api.CloudProfileConfig, cloudProfile *core.NamespacedCloudProfile, capabilityDefinitions []gardencorev1beta1.CapabilityDefinition) error {
+ cloudProfileConfigV1alpha1 := &v1alpha1.CloudProfileConfig{}
+ path := field.NewPath("spec").Child("providerConfig")
+
+ if err := helper.Scheme.Convert(cloudProfileConfig, cloudProfileConfigV1alpha1, nil); err != nil {
+ return field.InternalError(path, err)
+ }
+ namespacedCloudProfileSpecV1beta1 := gardencorev1beta1.NamespacedCloudProfileSpec{}
+ if err := gardencoreapi.Scheme.Convert(&cloudProfile.Spec, &namespacedCloudProfileSpecV1beta1, nil); err != nil {
+ return field.InternalError(path, err)
+ }
+
+ // simulate transformation to parent spec format
+ // - performed in mutating extension webhook
+ transformedSpecConfig := mutator.TransformProviderConfigToParentFormat(cloudProfileConfigV1alpha1, capabilityDefinitions)
+ // - performed in namespaced cloud profile controller
+ transformedSpec := gardenerutils.TransformSpecToParentFormat(namespacedCloudProfileSpecV1beta1, capabilityDefinitions)
+
+ if err := helper.Scheme.Convert(transformedSpecConfig, cloudProfileConfig, nil); err != nil {
+ return field.InternalError(path, err)
+ }
+ if err := gardencoreapi.Scheme.Convert(&transformedSpec, &cloudProfile.Spec, nil); err != nil {
+ return field.InternalError(path, err)
+ }
+ return nil
+}
diff --git a/pkg/provider-local/apis/local/v1alpha1/types_cloudprofile.go b/pkg/provider-local/apis/local/v1alpha1/types_cloudprofile.go
index 872f004b13c..7b95dad5ea3 100644
--- a/pkg/provider-local/apis/local/v1alpha1/types_cloudprofile.go
+++ b/pkg/provider-local/apis/local/v1alpha1/types_cloudprofile.go
@@ -36,7 +36,8 @@ type MachineImageVersion struct {
// Version is the version of the image.
Version string `json:"version"`
// Image is the image for the machine image.
- Image string `json:"image"`
+ // +optional
+ Image string `json:"image,omitempty"`
// CapabilityFlavors contains provider-specific image identifiers of this version with their capabilities.
CapabilityFlavors []MachineImageFlavor `json:"capabilityFlavors"`
}
diff --git a/pkg/provider-local/apis/local/validation/cloudprofile.go b/pkg/provider-local/apis/local/validation/cloudprofile.go
index 440b74fa081..eacaa36752c 100644
--- a/pkg/provider-local/apis/local/validation/cloudprofile.go
+++ b/pkg/provider-local/apis/local/validation/cloudprofile.go
@@ -149,8 +149,7 @@ func validateMachineImageMapping(coreMachineImages []core.MachineImage, machineI
// validate that for each machine image there is a corresponding cpConfig image
if _, existsInConfig := providerImages.GetImage(machineImage.Name); !existsInConfig {
- allErrs = append(allErrs, field.Required(machineImagePath,
- fmt.Sprintf("must provide an image mapping for image %q in providerConfig", machineImage.Name)))
+ allErrs = append(allErrs, field.Required(machineImagePath, fmt.Sprintf("must provide an image mapping for image %q in providerConfig", machineImage.Name)))
continue
}
@@ -177,8 +176,7 @@ func validateMachineImageVersionMapping(machineImage core.MachineImage, provider
imageVersion, exists := providerImages.GetImageVersion(machineImage.Name, version.Version)
if !exists {
allErrs = append(allErrs, field.Required(machineImageVersionPath,
- fmt.Sprintf("machine image version %s@%s is not defined in the providerConfig",
- machineImage.Name, version.Version),
+ fmt.Sprintf("machine image version %s@%s is not defined in the providerConfig", machineImage.Name, version.Version),
))
continue // Skip further validation if version doesn't exist
}
@@ -204,7 +202,7 @@ func validateImageFlavorMapping(imageName string, version core.MachineImageVersi
isFound := false
// search for the corresponding imageVersion.MachineImageFlavor
for _, providerFlavor := range imageVersion.CapabilityFlavors {
- providerDefaultedCapabilities := v1beta1helper.GetCapabilitiesWithAppliedDefaults(providerFlavor.Capabilities, capabilityDefinitions)
+ providerDefaultedCapabilities := gardencorev1beta1.GetCapabilitiesWithAppliedDefaults(providerFlavor.Capabilities, capabilityDefinitions)
if v1beta1helper.AreCapabilitiesEqual(coreDefaultedFlavor.Capabilities, providerDefaultedCapabilities) {
isFound = true
break
diff --git a/pkg/provider-local/controller/worker/machine_images.go b/pkg/provider-local/controller/worker/machine_images.go
index deecc266075..62ee1654ac1 100644
--- a/pkg/provider-local/controller/worker/machine_images.go
+++ b/pkg/provider-local/controller/worker/machine_images.go
@@ -93,10 +93,10 @@ func appendMachineImage(machineImages []api.MachineImage, machineImage api.Machi
})
}
- defaultedCapabilities := v1beta1helper.GetCapabilitiesWithAppliedDefaults(machineImage.Capabilities, capabilityDefinitions)
+ defaultedCapabilities := gardencorev1beta1.GetCapabilitiesWithAppliedDefaults(machineImage.Capabilities, capabilityDefinitions)
for _, existingMachineImage := range machineImages {
- existingDefaultedCapabilities := v1beta1helper.GetCapabilitiesWithAppliedDefaults(existingMachineImage.Capabilities, capabilityDefinitions)
+ existingDefaultedCapabilities := gardencorev1beta1.GetCapabilitiesWithAppliedDefaults(existingMachineImage.Capabilities, capabilityDefinitions)
if existingMachineImage.Name == machineImage.Name &&
existingMachineImage.Version == machineImage.Version &&
v1beta1helper.AreCapabilitiesEqual(defaultedCapabilities, existingDefaultedCapabilities) {
diff --git a/pkg/utils/gardener/cloudprofile.go b/pkg/utils/gardener/cloudprofile.go
index 1355adede2c..5630d1d2b7e 100644
--- a/pkg/utils/gardener/cloudprofile.go
+++ b/pkg/utils/gardener/cloudprofile.go
@@ -289,92 +289,111 @@ func SyncCloudProfileFields(oldShoot, newShoot *core.Shoot) {
// SyncArchitectureCapabilityFields syncs the architecture capabilities and the architecture fields.
func SyncArchitectureCapabilityFields(newCloudProfileSpec core.CloudProfileSpec, oldCloudProfileSpec core.CloudProfileSpec) {
- hasCapabilities := len(newCloudProfileSpec.MachineCapabilities) > 0
- if !hasCapabilities || !gardencorehelper.HasCapability(newCloudProfileSpec.MachineCapabilities, v1beta1constants.ArchitectureName) {
- return
+ hasNewCapabilities := len(newCloudProfileSpec.MachineCapabilities) > 0
+ hasOldCapabilities := len(oldCloudProfileSpec.MachineCapabilities) > 0
+ isInitialMigration := !hasOldCapabilities && hasNewCapabilities
+
+ if isInitialMigration {
+ machineCapabilities := gardencorehelper.CapabilityDefinitionsToCapabilities(newCloudProfileSpec.MachineCapabilities)
+ numberOfCloudProfileArchitectures := len(machineCapabilities[v1beta1constants.ArchitectureName])
+ // syncing is only required if there is more than 1 architecture in spec.machineCapabilities
+ // 0: means the MachineCapabilities are invalid and will be caught by validation
+ // 1: means we have only one architecture and no syncing is required
+ if numberOfCloudProfileArchitectures > 1 {
+ // During the initial migration to capabilities, synchronize the legacy architecture fields with the architecture capability values.
+ // Any mismatch between capabilities and architecture fields will result in a validation error.
+ syncMachineImageArchitectureCapabilities(newCloudProfileSpec.MachineImages)
+ syncMachineTypeArchitectureCapabilities(newCloudProfileSpec.MachineTypes)
+ }
+ }
+ if hasNewCapabilities || hasOldCapabilities {
+ // sync back the legacy architecture fields from the capabilities on every update
+ // or if only the old cloud profile has capabilities defined assign them to nil to allow switching back to legacy mode
+ syncMachineImageLegacyArchitecture(newCloudProfileSpec.MachineImages, newCloudProfileSpec.MachineCapabilities)
+ syncMachineTypeLegacyArchitecture(newCloudProfileSpec.MachineTypes, newCloudProfileSpec.MachineCapabilities)
}
-
- isInitialMigration := hasCapabilities && len(oldCloudProfileSpec.MachineCapabilities) == 0
-
- // During the initial migration to capabilities, synchronize the architecture fields with the capability definitions.
- // After the migration, only sync architectures from the capability definitions back to the architecture fields.
- // This approach ensures that capabilities are consistently used once defined.
- // Any mismatch between capabilities and architecture fields will result in a validation error.
- syncMachineImageArchitectureCapabilities(newCloudProfileSpec.MachineImages, oldCloudProfileSpec.MachineImages, isInitialMigration)
- syncMachineTypeArchitectureCapabilities(newCloudProfileSpec.MachineTypes, oldCloudProfileSpec.MachineTypes, isInitialMigration)
}
-func syncMachineImageArchitectureCapabilities(newMachineImages, oldMachineImages []core.MachineImage, isInitialMigration bool) {
- oldMachineImagesMap := NewCoreImagesContext(oldMachineImages)
-
- for imageIdx, image := range newMachineImages {
- for versionIdx, version := range newMachineImages[imageIdx].Versions {
- oldMachineImageVersion, oldVersionExists := oldMachineImagesMap.GetImageVersion(image.Name, version.Version)
- capabilityArchitectures := gardencorehelper.ExtractArchitecturesFromImageFlavors(version.CapabilityFlavors)
-
- // Skip any architecture field syncing if
- // - architecture field has been modified and changed to any value other than empty.
- architecturesFieldHasBeenChanged := oldVersionExists && len(version.Architectures) > 0 &&
- !apiequality.Semantic.DeepEqual(oldMachineImageVersion.Architectures, version.Architectures)
-
- // - both the architecture field and the architecture capability are empty or filled equally.
- if architecturesFieldHasBeenChanged || slices.Equal(capabilityArchitectures, version.Architectures) {
+func syncMachineImageLegacyArchitecture(newMachineImages []core.MachineImage, capabilityDefinitions []core.CapabilityDefinition) {
+ for imageIdx := range newMachineImages {
+ for versionIdx, imageVersion := range newMachineImages[imageIdx].Versions {
+ // If there are no capability definitions, clear capability flavors.
+ if len(capabilityDefinitions) == 0 {
+ newMachineImages[imageIdx].Versions[versionIdx].CapabilityFlavors = nil
continue
}
- // Sync architecture field to capabilities if filled on initial migration.
- if isInitialMigration && len(version.Architectures) > 0 && len(version.CapabilityFlavors) == 0 {
- for _, architecture := range version.Architectures {
- newMachineImages[imageIdx].Versions[versionIdx].CapabilityFlavors = append(newMachineImages[imageIdx].Versions[versionIdx].CapabilityFlavors,
- core.MachineImageFlavor{
- Capabilities: core.Capabilities{
- v1beta1constants.ArchitectureName: []string{architecture},
- },
- })
- }
+ // don't sync if architectures are set by the user
+ if len(imageVersion.Architectures) > 0 {
continue
}
-
// Sync capability architectures to architectures field.
- if len(capabilityArchitectures) > 0 {
- newMachineImages[imageIdx].Versions[versionIdx].Architectures = capabilityArchitectures
+ defaultedImageFlavors := gardencorehelper.GetImageFlavorsWithAppliedDefaults(imageVersion.CapabilityFlavors, capabilityDefinitions)
+ defaultArchitectures := gardencorehelper.ExtractArchitecturesFromImageFlavors(defaultedImageFlavors)
+ if len(defaultArchitectures) > 0 {
+ newMachineImages[imageIdx].Versions[versionIdx].Architectures = defaultArchitectures
}
}
}
}
-func syncMachineTypeArchitectureCapabilities(newMachineTypes, oldMachineTypes []core.MachineType, isInitialMigration bool) {
- oldMachineTypesMap := utils.CreateMapFromSlice(oldMachineTypes, func(machineType core.MachineType) string { return machineType.Name })
-
+func syncMachineTypeLegacyArchitecture(newMachineTypes []core.MachineType, capabilityDefinitions []core.CapabilityDefinition) {
for i, machineType := range newMachineTypes {
- oldMachineType, oldMachineTypeExists := oldMachineTypesMap[machineType.Name]
- architectureValue := ptr.Deref(machineType.Architecture, "")
- oldArchitectureValue := ptr.Deref(oldMachineType.Architecture, "")
- capabilityArchitectures := machineType.Capabilities[v1beta1constants.ArchitectureName]
-
- // Skip any architecture field syncing if
- // - architecture field has been modified and changed to any value other than empty.
- architectureFieldHasBeenChanged := oldMachineTypeExists && architectureValue != "" &&
- (oldArchitectureValue == "" || oldArchitectureValue != architectureValue)
- // - both the architecture field and the architecture capability are empty or filled equally.
- architecturesInSync := len(capabilityArchitectures) == 0 && architectureValue == "" ||
- len(capabilityArchitectures) == 1 && capabilityArchitectures[0] == architectureValue
- if architectureFieldHasBeenChanged || architecturesInSync {
+ // If there are no capability definitions, clear capability flavors.
+ if len(capabilityDefinitions) == 0 {
+ newMachineTypes[i].Capabilities = nil
continue
}
- // Sync architecture field to capabilities if filled on initial migration.
- if isInitialMigration && architectureValue != "" && len(capabilityArchitectures) == 0 {
- if newMachineTypes[i].Capabilities == nil {
- newMachineTypes[i].Capabilities = make(core.Capabilities)
- }
- newMachineTypes[i].Capabilities[v1beta1constants.ArchitectureName] = []string{architectureValue}
+ // don't sync if architecture is set by the user
+ if machineType.Architecture != nil {
continue
}
// Sync capability architecture to architecture field.
- if len(capabilityArchitectures) == 1 {
- newMachineTypes[i].Architecture = ptr.To(capabilityArchitectures[0])
+ defaultedCapabilities := core.GetCapabilitiesWithAppliedDefaults(newMachineTypes[i].Capabilities, capabilityDefinitions)
+ if len(defaultedCapabilities[v1beta1constants.ArchitectureName]) == 1 {
+ newMachineTypes[i].Architecture = ptr.To(defaultedCapabilities[v1beta1constants.ArchitectureName][0])
+ }
+ }
+}
+
+func syncMachineImageArchitectureCapabilities(newMachineImages []core.MachineImage) {
+ for imageIdx := range newMachineImages {
+ for versionIdx, version := range newMachineImages[imageIdx].Versions {
+ // don't sync if capabilities are set by the user
+ if len(version.CapabilityFlavors) > 0 {
+ continue
+ }
+
+ legacyArchitectures := version.Architectures
+ if len(legacyArchitectures) == 0 {
+ // default to AMD64 if empty as this is the default for the architecture field
+ legacyArchitectures = []string{v1beta1constants.ArchitectureAMD64}
+ }
+ for _, architecture := range legacyArchitectures {
+ newMachineImages[imageIdx].Versions[versionIdx].CapabilityFlavors = append(newMachineImages[imageIdx].Versions[versionIdx].CapabilityFlavors,
+ core.MachineImageFlavor{Capabilities: core.Capabilities{
+ v1beta1constants.ArchitectureName: []string{architecture},
+ }},
+ )
+ }
+ }
+ }
+}
+
+func syncMachineTypeArchitectureCapabilities(newMachineTypes []core.MachineType) {
+ for i, machineType := range newMachineTypes {
+ // don't sync if capabilities are set by the user
+ if len(machineType.Capabilities) > 0 {
+ continue
+ }
+
+ // default to AMD64 if empty as this is the default for the architecture field
+ legacyArchitecture := ptr.Deref(machineType.Architecture, v1beta1constants.ArchitectureAMD64)
+
+ newMachineTypes[i].Capabilities = core.Capabilities{
+ v1beta1constants.ArchitectureName: []string{legacyArchitecture},
}
}
}
diff --git a/pkg/utils/gardener/cloudprofile_test.go b/pkg/utils/gardener/cloudprofile_test.go
index 47ef61fee76..a9e919664d6 100644
--- a/pkg/utils/gardener/cloudprofile_test.go
+++ b/pkg/utils/gardener/cloudprofile_test.go
@@ -748,6 +748,9 @@ var _ = Describe("CloudProfile", func() {
BeforeEach(func() {
cloudProfileSpecNew = core.CloudProfileSpec{
+ MachineCapabilities: []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"arm64", "amd64", "custom"}},
+ },
MachineImages: []core.MachineImage{
{Versions: []core.MachineImageVersion{{}}},
},
@@ -755,51 +758,102 @@ var _ = Describe("CloudProfile", func() {
{},
},
}
- cloudProfileSpecOld = cloudProfileSpecNew
+ cloudProfileSpecOld = *cloudProfileSpecNew.DeepCopy()
+ cloudProfileSpecOld.MachineCapabilities = []core.CapabilityDefinition{}
})
- Describe("Initial migration", func() {
- BeforeEach(func() {
- cloudProfileSpecNew.MachineCapabilities = []core.CapabilityDefinition{
- {Name: "architecture", Values: []string{"arm64", "amd64", "custom"}},
- }
- })
+ It("should do nothing if its NOT the initial migration", func() {
+ // its no initial migration if both old and new have machineCapabilities defined
+ cloudProfileSpecOld.MachineCapabilities = []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"arm64", "amd64"}},
+ }
- It("It should do nothing for empty architectures and empty capabilities", func() {
- cloudProfileSpecNewBefore := cloudProfileSpecNew
- // With the update, the old fields are unset:
- cloudProfileSpecOld.MachineImages[0].Versions[0].Architectures = []string{"amd64"}
- cloudProfileSpecOld.MachineTypes[0].Architecture = ptr.To("amd64")
+ cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures = []string{"amd64"}
+ cloudProfileSpecNew.MachineTypes[0].Architecture = ptr.To("amd64")
+ initialNewSpec := *cloudProfileSpecNew.DeepCopy()
- gardenerutils.SyncArchitectureCapabilityFields(cloudProfileSpecNew, cloudProfileSpecOld)
+ gardenerutils.SyncArchitectureCapabilityFields(cloudProfileSpecNew, cloudProfileSpecOld)
+ Expect(cloudProfileSpecNew).To(Equal(initialNewSpec))
+ })
- Expect(cloudProfileSpecNew).To(Equal(cloudProfileSpecNewBefore))
- })
+ It("should do nothing if less than two architectures are supported", func() {
+ cloudProfileSpecNew.MachineCapabilities = []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"amd64"}},
+ }
+ cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures = []string{"amd64"}
+ cloudProfileSpecNew.MachineTypes[0].Architecture = ptr.To("amd64")
- It("It should correctly handle split-up machine image version capability architectures", func() {
- cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors = []core.MachineImageFlavor{
- {Capabilities: core.Capabilities{"architecture": []string{"custom"}}},
- {Capabilities: core.Capabilities{"architecture": []string{"amd64"}}},
- {Capabilities: core.Capabilities{"architecture": []string{"arm64"}}},
- }
+ initialNewSpec := *cloudProfileSpecNew.DeepCopy()
- gardenerutils.SyncArchitectureCapabilityFields(cloudProfileSpecNew, cloudProfileSpecOld)
+ gardenerutils.SyncArchitectureCapabilityFields(cloudProfileSpecNew, cloudProfileSpecOld)
+ Expect(cloudProfileSpecNew).To(Equal(initialNewSpec))
+ })
- Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures).To(ConsistOf("amd64", "arm64", "custom"))
- })
+ It("should create capabilities and capabilityFlavors from architecture fields if they are empty", func() {
+ cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures = []string{"amd64", "arm64"}
+ cloudProfileSpecNew.MachineTypes[0].Architecture = ptr.To("arm64")
- It("It should sync filled architecture fields to empty capabilities", func() {
- cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures = []string{"amd64", "arm64"}
- cloudProfileSpecNew.MachineTypes[0].Architecture = ptr.To("amd64")
+ gardenerutils.SyncArchitectureCapabilityFields(cloudProfileSpecNew, cloudProfileSpecOld)
- gardenerutils.SyncArchitectureCapabilityFields(cloudProfileSpecNew, cloudProfileSpecOld)
+ Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures).To(Equal([]string{"amd64", "arm64"}))
+ Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors[0].Capabilities["architecture"]).To(BeEquivalentTo([]string{"amd64"}))
+ Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors[1].Capabilities["architecture"]).To(BeEquivalentTo([]string{"arm64"}))
+ Expect(cloudProfileSpecNew.MachineTypes[0].Architecture).To(Equal(ptr.To("arm64")))
+ Expect(cloudProfileSpecNew.MachineTypes[0].Capabilities["architecture"]).To(BeEquivalentTo([]string{"arm64"}))
+ })
- Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures).To(Equal([]string{"amd64", "arm64"}))
- Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors[0].Capabilities["architecture"]).To(BeEquivalentTo([]string{"amd64"}))
- Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors[1].Capabilities["architecture"]).To(BeEquivalentTo([]string{"arm64"}))
- Expect(cloudProfileSpecNew.MachineTypes[0].Architecture).To(Equal(ptr.To("amd64")))
- Expect(cloudProfileSpecNew.MachineTypes[0].Capabilities["architecture"]).To(BeEquivalentTo([]string{"amd64"}))
+ It("should not write to capabilities if they are already set", func() {
+ cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures = []string{"amd64", "arm64"}
+ cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors = []core.MachineImageFlavor{
+ {Capabilities: core.Capabilities{"architecture": []string{"custom"}}},
+ }
+ cloudProfileSpecNew.MachineTypes[0].Architecture = ptr.To("amd64")
+ cloudProfileSpecNew.MachineTypes[0].Capabilities = core.Capabilities{
+ "architecture": []string{"custom"},
+ }
+ cloudProfileSpecNew.MachineTypes = append(cloudProfileSpecNew.MachineTypes, core.MachineType{
+ Architecture: ptr.To("amd64"),
})
+
+ gardenerutils.SyncArchitectureCapabilityFields(cloudProfileSpecNew, cloudProfileSpecOld)
+
+ Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures).To(Equal([]string{"amd64", "arm64"}))
+ Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors).To(HaveLen(1))
+ Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors[0].Capabilities["architecture"]).To(BeEquivalentTo([]string{"custom"}))
+ Expect(cloudProfileSpecNew.MachineTypes[0].Architecture).To(Equal(ptr.To("amd64")))
+ Expect(cloudProfileSpecNew.MachineTypes[0].Capabilities["architecture"]).To(BeEquivalentTo([]string{"custom"}))
+ Expect(cloudProfileSpecNew.MachineTypes[1].Architecture).To(Equal(ptr.To("amd64")))
+ Expect(cloudProfileSpecNew.MachineTypes[1].Capabilities["architecture"]).To(BeEquivalentTo([]string{"amd64"}))
+ })
+
+ It("should use the default architecture amd64 if architecture field is empty and capabilities are empty", func() {
+ gardenerutils.SyncArchitectureCapabilityFields(cloudProfileSpecNew, cloudProfileSpecOld)
+ Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].Architectures).To(Equal([]string{"amd64"}))
+ Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors[0].Capabilities["architecture"]).To(BeEquivalentTo([]string{"amd64"}))
+ Expect(cloudProfileSpecNew.MachineTypes[0].Architecture).To(Equal(ptr.To("amd64")))
+ Expect(cloudProfileSpecNew.MachineTypes[0].Capabilities["architecture"]).To(BeEquivalentTo([]string{"amd64"}))
+ })
+
+ It("should set capabilities and capabilityFlavors to nil on migration to legacy format", func() {
+ // migration to legacy is indicated by old spec having machineCapabilities defined
+ // and new spec having empty machineCapabilities
+ cloudProfileSpecOld.MachineCapabilities = []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"arm64", "amd64"}},
+ }
+ cloudProfileSpecNew.MachineCapabilities = []core.CapabilityDefinition{}
+
+ cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors = []core.MachineImageFlavor{
+ {Capabilities: core.Capabilities{"architecture": []string{"amd64"}}},
+ {Capabilities: core.Capabilities{"architecture": []string{"arm64"}}},
+ }
+ cloudProfileSpecNew.MachineTypes[0].Capabilities = core.Capabilities{
+ "architecture": []string{"arm64"},
+ }
+
+ gardenerutils.SyncArchitectureCapabilityFields(cloudProfileSpecNew, cloudProfileSpecOld)
+
+ Expect(cloudProfileSpecNew.MachineImages[0].Versions[0].CapabilityFlavors).To(BeNil())
+ Expect(cloudProfileSpecNew.MachineTypes[0].Capabilities).To(BeNil())
})
})
diff --git a/pkg/utils/gardener/namespacedcloudprofile.go b/pkg/utils/gardener/namespacedcloudprofile.go
new file mode 100644
index 00000000000..780cdbad038
--- /dev/null
+++ b/pkg/utils/gardener/namespacedcloudprofile.go
@@ -0,0 +1,87 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package gardener
+
+import (
+ "k8s.io/apimachinery/pkg/util/sets"
+ "k8s.io/utils/ptr"
+
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+)
+
+// TransformSpecToParentFormat ensures that the given NamespacedCloudProfileSpec is in a uniform format with its parent CloudProfileSpec.
+// If the parent CloudProfileSpec uses capability definitions, then the NamespacedCloudProfileSpec is transformed to also use capabilities
+// and vice versa.
+// TODO(Roncossek): Remove TransformSpecToParentFormat once all CloudProfiles have been migrated to use CapabilityFlavors and the Architecture fields are effectively forbidden or have been removed.
+func TransformSpecToParentFormat(
+ spec gardencorev1beta1.NamespacedCloudProfileSpec,
+ capabilityDefinitions []gardencorev1beta1.CapabilityDefinition,
+) gardencorev1beta1.NamespacedCloudProfileSpec {
+ isParentInCapabilityFormat := len(capabilityDefinitions) > 0
+ transformedSpec := spec.DeepCopy()
+
+ // Normalize MachineImages
+ for idx, machineImage := range transformedSpec.MachineImages {
+ for idy, version := range machineImage.Versions {
+ legacyArchitectures := version.Architectures
+
+ if isParentInCapabilityFormat && len(version.CapabilityFlavors) == 0 {
+ // Convert legacy architectures to capability flavors
+ version.CapabilityFlavors = []gardencorev1beta1.MachineImageFlavor{}
+ for _, arch := range legacyArchitectures {
+ version.CapabilityFlavors = append(version.CapabilityFlavors, gardencorev1beta1.MachineImageFlavor{
+ Capabilities: gardencorev1beta1.Capabilities{
+ v1beta1constants.ArchitectureName: []string{arch},
+ },
+ })
+ }
+ version.Architectures = legacyArchitectures
+ } else if !isParentInCapabilityFormat {
+ // Convert capability flavors to legacy architectures
+ if len(legacyArchitectures) == 0 {
+ architectureSet := sets.New[string]()
+ if len(version.CapabilityFlavors) > 0 {
+ for _, flavor := range version.CapabilityFlavors {
+ architectureSet.Insert(flavor.Capabilities[v1beta1constants.ArchitectureName]...)
+ }
+ }
+ version.Architectures = architectureSet.UnsortedList()
+ }
+ version.CapabilityFlavors = nil
+ }
+
+ transformedSpec.MachineImages[idx].Versions[idy] = version
+ }
+ }
+
+ // Normalize MachineTypes
+ for idx, machineType := range transformedSpec.MachineTypes {
+ if isParentInCapabilityFormat {
+ if len(machineType.Capabilities) > 0 {
+ continue
+ }
+ architecture := machineType.GetArchitecture(capabilityDefinitions)
+ if architecture == "" {
+ architecture = ptr.Deref(machineType.Architecture, v1beta1constants.ArchitectureAMD64)
+ }
+ machineType.Capabilities = gardencorev1beta1.Capabilities{
+ v1beta1constants.ArchitectureName: []string{architecture},
+ }
+ } else {
+ if machineType.Architecture == nil {
+ if len(machineType.Capabilities) > 0 {
+ architecture := machineType.Capabilities[v1beta1constants.ArchitectureName]
+ if len(architecture) > 0 {
+ machineType.Architecture = &architecture[0]
+ }
+ }
+ }
+ machineType.Capabilities = nil
+ }
+ transformedSpec.MachineTypes[idx] = machineType
+ }
+ return *transformedSpec
+}
diff --git a/pkg/utils/gardener/namespacedcloudprofile_test.go b/pkg/utils/gardener/namespacedcloudprofile_test.go
new file mode 100644
index 00000000000..d0bb148ce31
--- /dev/null
+++ b/pkg/utils/gardener/namespacedcloudprofile_test.go
@@ -0,0 +1,380 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package gardener_test
+
+import (
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ "k8s.io/apimachinery/pkg/api/resource"
+ "k8s.io/utils/ptr"
+
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ . "github.com/gardener/gardener/pkg/utils/gardener"
+)
+
+var _ = Describe("TransformSpecToParentFormat", func() {
+ When("parent uses capabilities", func() {
+ var capabilityDefinitions []gardencorev1beta1.CapabilityDefinition
+
+ BeforeEach(func() {
+ capabilityDefinitions = []gardencorev1beta1.CapabilityDefinition{
+ {
+ Name: v1beta1constants.ArchitectureName,
+ Values: []string{"amd64", "arm64"},
+ },
+ }
+ })
+
+ It("should transform legacy architectures to capability flavors", func() {
+ spec := gardencorev1beta1.NamespacedCloudProfileSpec{
+ MachineImages: []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{
+ Version: "20.04",
+ },
+ Architectures: []string{"amd64", "arm64"},
+ },
+ },
+ },
+ },
+ MachineTypes: []gardencorev1beta1.MachineType{
+ {
+ Name: "m5.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ Architecture: ptr.To("amd64"),
+ },
+ },
+ }
+
+ result := TransformSpecToParentFormat(spec, capabilityDefinitions)
+
+ Expect(result.MachineImages).To(HaveLen(1))
+ Expect(result.MachineImages[0].Versions).To(HaveLen(1))
+ version := result.MachineImages[0].Versions[0]
+ Expect(version.Architectures).To(Equal([]string{"amd64", "arm64"}))
+ Expect(version.CapabilityFlavors).To(HaveLen(2))
+ Expect(version.CapabilityFlavors[0].Capabilities[v1beta1constants.ArchitectureName]).To(BeEquivalentTo([]string{"amd64"}))
+ Expect(version.CapabilityFlavors[1].Capabilities[v1beta1constants.ArchitectureName]).To(BeEquivalentTo([]string{"arm64"}))
+
+ Expect(result.MachineTypes).To(HaveLen(1))
+ machineType := result.MachineTypes[0]
+ Expect(machineType.Architecture).To(Equal(ptr.To("amd64")))
+ Expect(machineType.Capabilities[v1beta1constants.ArchitectureName]).To(BeEquivalentTo([]string{"amd64"}))
+ })
+
+ It("should preserve existing capability flavors when already present", func() {
+ spec := gardencorev1beta1.NamespacedCloudProfileSpec{
+ MachineImages: []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{
+ Version: "20.04",
+ },
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ v1beta1constants.ArchitectureName: []string{"amd64"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ MachineTypes: []gardencorev1beta1.MachineType{
+ {
+ Name: "m5.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ Capabilities: gardencorev1beta1.Capabilities{
+ v1beta1constants.ArchitectureName: []string{"amd64"},
+ },
+ },
+ },
+ }
+
+ result := TransformSpecToParentFormat(spec, capabilityDefinitions)
+
+ Expect(result.MachineImages[0].Versions[0].CapabilityFlavors).To(HaveLen(1))
+ Expect(result.MachineImages[0].Versions[0].CapabilityFlavors[0].Capabilities[v1beta1constants.ArchitectureName]).To(BeEquivalentTo([]string{"amd64"}))
+ Expect(result.MachineTypes[0].Capabilities[v1beta1constants.ArchitectureName]).To(BeEquivalentTo([]string{"amd64"}))
+ })
+
+ It("should default to AMD64 for machine types without architecture", func() {
+ spec := gardencorev1beta1.NamespacedCloudProfileSpec{
+ MachineTypes: []gardencorev1beta1.MachineType{
+ {
+ Name: "m5.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ },
+ },
+ }
+
+ result := TransformSpecToParentFormat(spec, capabilityDefinitions)
+
+ Expect(result.MachineTypes[0].Capabilities[v1beta1constants.ArchitectureName]).To(BeEquivalentTo([]string{"amd64"}))
+ })
+ })
+
+ When("parent doesn't use capabilities", func() {
+ It("should transform capability flavors to legacy architectures", func() {
+ spec := gardencorev1beta1.NamespacedCloudProfileSpec{
+ MachineImages: []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{
+ Version: "20.04",
+ },
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ v1beta1constants.ArchitectureName: []string{"amd64"},
+ },
+ },
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ v1beta1constants.ArchitectureName: []string{"arm64"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ MachineTypes: []gardencorev1beta1.MachineType{
+ {
+ Name: "m5.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ Capabilities: gardencorev1beta1.Capabilities{
+ v1beta1constants.ArchitectureName: []string{"amd64"},
+ },
+ },
+ },
+ }
+
+ result := TransformSpecToParentFormat(spec, nil)
+
+ Expect(result.MachineImages[0].Versions[0].Architectures).To(ConsistOf("amd64", "arm64"))
+ Expect(result.MachineImages[0].Versions[0].CapabilityFlavors).To(BeNil())
+ Expect(result.MachineTypes[0].Capabilities).To(BeNil())
+ Expect(result.MachineTypes[0].Architecture).To(Equal(ptr.To("amd64")))
+ })
+
+ It("should leave architectures empty for machine image versions with empty capability flavors, to not overwrite images during deepMerge", func() {
+ spec := gardencorev1beta1.NamespacedCloudProfileSpec{
+ MachineImages: []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{
+ Version: "20.04",
+ },
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{},
+ },
+ },
+ },
+ },
+ }
+
+ result := TransformSpecToParentFormat(spec, nil)
+
+ Expect(result.MachineImages[0].Versions[0].Architectures).To(BeEmpty())
+ })
+ })
+
+ It("should handle multiple machine images and types correctly", func() {
+ spec := gardencorev1beta1.NamespacedCloudProfileSpec{
+ MachineImages: []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{
+ Version: "20.04",
+ },
+ Architectures: []string{"amd64"},
+ },
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{
+ Version: "22.04",
+ },
+ Architectures: []string{"arm64"},
+ },
+ },
+ },
+ {
+ Name: "debian",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{
+ Version: "11",
+ },
+ Architectures: []string{"amd64", "arm64"},
+ },
+ },
+ },
+ },
+ MachineTypes: []gardencorev1beta1.MachineType{
+ {
+ Name: "m5.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ Architecture: ptr.To("amd64"),
+ },
+ {
+ Name: "m6g.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ Architecture: ptr.To("arm64"),
+ },
+ },
+ }
+
+ capabilityDefinitions := []gardencorev1beta1.CapabilityDefinition{
+ {
+ Name: v1beta1constants.ArchitectureName,
+ Values: []string{"amd64", "arm64"},
+ },
+ }
+
+ result := TransformSpecToParentFormat(spec, capabilityDefinitions)
+
+ // Verify all machine images have capability flavors
+ Expect(result.MachineImages).To(ConsistOf(gardencorev1beta1.MachineImage{
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "20.04"},
+ Architectures: []string{"amd64"},
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": {"amd64"},
+ },
+ },
+ },
+ },
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "22.04"},
+ Architectures: []string{"arm64"},
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": {"arm64"},
+ },
+ },
+ },
+ },
+ },
+ },
+ gardencorev1beta1.MachineImage{
+ Name: "debian",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "11"},
+ Architectures: []string{"amd64", "arm64"},
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": {"amd64"},
+ },
+ },
+ {
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": {"arm64"},
+ },
+ },
+ },
+ },
+ },
+ }))
+ // Verify all machine types have capabilities
+ Expect(result.MachineTypes).To(Equal([]gardencorev1beta1.MachineType{
+ {
+ Name: "m5.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ Architecture: ptr.To("amd64"),
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": {"amd64"},
+ },
+ },
+ {
+ Name: "m6g.large",
+ CPU: resource.MustParse("2"),
+ Memory: resource.MustParse("8Gi"),
+ Architecture: ptr.To("arm64"),
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": {"arm64"},
+ },
+ },
+ }))
+ })
+
+ It("should return empty spec for empty input", func() {
+ spec := gardencorev1beta1.NamespacedCloudProfileSpec{}
+ capabilityDefinitions := []gardencorev1beta1.CapabilityDefinition{
+ {
+ Name: v1beta1constants.ArchitectureName,
+ Values: []string{"amd64", "arm64"},
+ },
+ }
+
+ result := TransformSpecToParentFormat(spec, capabilityDefinitions)
+
+ Expect(result).To(Equal(gardencorev1beta1.NamespacedCloudProfileSpec{}))
+ })
+
+ It("should not modify the original spec (deep copy behavior)", func() {
+ originalSpec := gardencorev1beta1.NamespacedCloudProfileSpec{
+ MachineImages: []gardencorev1beta1.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{
+ Version: "20.04",
+ },
+ Architectures: []string{"amd64"},
+ },
+ },
+ },
+ },
+ }
+
+ capabilityDefinitions := []gardencorev1beta1.CapabilityDefinition{
+ {
+ Name: v1beta1constants.ArchitectureName,
+ Values: []string{"amd64", "arm64"},
+ },
+ }
+
+ // Keep references to verify original is unchanged
+ originalArchitectures := originalSpec.MachineImages[0].Versions[0].Architectures
+ originalCapabilityFlavors := originalSpec.MachineImages[0].Versions[0].CapabilityFlavors
+
+ result := TransformSpecToParentFormat(originalSpec, capabilityDefinitions)
+
+ // Original should remain unchanged
+ Expect(originalSpec.MachineImages[0].Versions[0].Architectures).To(Equal(originalArchitectures))
+ Expect(originalSpec.MachineImages[0].Versions[0].CapabilityFlavors).To(Equal(originalCapabilityFlavors))
+
+ // Result should have capability flavors added
+ Expect(result.MachineImages[0].Versions[0].CapabilityFlavors).ToNot(BeNil())
+ Expect(result.MachineImages[0].Versions[0].CapabilityFlavors).To(HaveLen(1))
+ })
+})
diff --git a/plugin/pkg/global/resourcereferencemanager/admission.go b/plugin/pkg/global/resourcereferencemanager/admission.go
index 5388fd21854..1fbaf4ed2bd 100644
--- a/plugin/pkg/global/resourcereferencemanager/admission.go
+++ b/plugin/pkg/global/resourcereferencemanager/admission.go
@@ -489,9 +489,12 @@ func (r *ReferenceManager) Validate(ctx context.Context, a admission.Attributes,
// getting Machine image versions that have been removed from or added to the CloudProfile
removedMachineImages, removedMachineImageVersions, addedMachineImages, addedMachineImageVersions := helper.GetMachineImageDiff(oldCloudProfile.Spec.MachineImages, cloudProfile.Spec.MachineImages)
+ // getting removed capabilities
+ removedCapabilities := getRemovedMachineCapabilities(oldCloudProfile.Spec.MachineCapabilities, cloudProfile.Spec.MachineCapabilities)
+
wasLimitAdded := !apiequality.Semantic.DeepEqual(cloudProfile.Spec.Limits, oldCloudProfile.Spec.Limits)
- if len(removedKubernetesVersions) > 0 || len(removedMachineImageVersions) > 0 || len(addedMachineImageVersions) > 0 || wasLimitAdded {
+ if len(removedKubernetesVersions) > 0 || len(removedMachineImageVersions) > 0 || len(addedMachineImageVersions) > 0 || wasLimitAdded || len(removedCapabilities) > 0 {
shootList, err1 := r.shootLister.List(labels.Everything())
if err1 != nil {
return apierrors.NewInternalError(fmt.Errorf("could not list shoots to verify that Kubernetes and/or Machine image version can be removed: %v", err1))
@@ -547,6 +550,10 @@ func (r *ReferenceManager) Validate(ctx context.Context, a admission.Attributes,
}
}
}
+ checkMachineImageForRemovedCapabilities(machineImage, removedCapabilities, nscpfl, cloudProfile, channel)
+ }
+ for _, machineType := range nscpfl.Spec.MachineTypes {
+ checkMachineTypeForRemovedCapabilities(machineType, removedCapabilities, nscpfl, cloudProfile, channel)
}
}(ncp)
}
@@ -712,6 +719,34 @@ func (r *ReferenceManager) Validate(ctx context.Context, a admission.Attributes,
return nil
}
+func checkMachineTypeForRemovedCapabilities(machineType gardencorev1beta1.MachineType, removedCapabilities []core.CapabilityDefinition, nscpfl *gardencorev1beta1.NamespacedCloudProfile, cloudProfile *core.CloudProfile, channel chan error) {
+ for _, removedCapability := range removedCapabilities {
+ if capabilityValues, exist := machineType.Capabilities[removedCapability.Name]; exist {
+ for _, capabilityValue := range capabilityValues {
+ if slices.Contains(removedCapability.Values, capabilityValue) {
+ channel <- fmt.Errorf("unable to delete MachineCapability %q with value %q from CloudProfile %q - capability value is still in use by NamespacedCloudProfile '%s/%s'", removedCapability.Name, capabilityValue, cloudProfile.Name, nscpfl.Namespace, nscpfl.Name)
+ }
+ }
+ }
+ }
+}
+
+func checkMachineImageForRemovedCapabilities(machineImage gardencorev1beta1.MachineImage, removedCapabilities []core.CapabilityDefinition, nscpfl *gardencorev1beta1.NamespacedCloudProfile, cloudProfile *core.CloudProfile, channel chan error) {
+ for _, imageVersion := range machineImage.Versions {
+ for _, imageFlavor := range imageVersion.CapabilityFlavors {
+ for _, removedCapability := range removedCapabilities {
+ if capabilityValues, exist := imageFlavor.Capabilities[removedCapability.Name]; exist {
+ for _, capabilityValue := range capabilityValues {
+ if slices.Contains(removedCapability.Values, capabilityValue) {
+ channel <- fmt.Errorf("unable to delete MachineCapability %q with value %q from CloudProfile %q - capability value is still in use by NamespacedCloudProfile '%s/%s'", removedCapability.Name, capabilityValue, cloudProfile.Name, nscpfl.Namespace, nscpfl.Name)
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
func (r *ReferenceManager) ensureControllerRegistrationReferences(ctx context.Context, ctrlReg *core.ControllerRegistration) error {
deployment := ctrlReg.Spec.Deployment
if ctrlReg.Spec.Deployment == nil {
@@ -1399,3 +1434,32 @@ func (r *ReferenceManager) sanityCheckProviderSecret(ctx context.Context, namesp
func isGardenadmUser(userInfo user.Info) bool {
return slices.Contains(userInfo.GetGroups(), v1beta1constants.ShootsGroup) && strings.HasPrefix(userInfo.GetName(), v1beta1constants.GardenadmUserNamePrefix)
}
+
+// getRemovedMachineCapabilities returns the removed capabilities and their removed values.
+func getRemovedMachineCapabilities(old, new []core.CapabilityDefinition) []core.CapabilityDefinition {
+ var (
+ removedCapabilities []core.CapabilityDefinition
+ oldCapabilitiesMap = utils.CreateMapFromSlice(old, func(capability core.CapabilityDefinition) string { return capability.Name })
+ newCapabilitiesMap = utils.CreateMapFromSlice(new, func(capability core.CapabilityDefinition) string { return capability.Name })
+ )
+
+ for capabilityName, oldCapability := range oldCapabilitiesMap {
+ newCapability, exists := newCapabilitiesMap[capabilityName]
+ if !exists {
+ // Completely removed capability.
+ removedCapabilities = append(removedCapabilities, oldCapability)
+ } else {
+ // Collect removed capability values.
+ oldValuesSet := sets.New[string](oldCapability.Values...)
+ newValuesSet := sets.New[string](newCapability.Values...)
+
+ if removedValues := oldValuesSet.Difference(newValuesSet); removedValues.Len() > 0 {
+ removedCapabilities = append(removedCapabilities, core.CapabilityDefinition{
+ Name: capabilityName,
+ Values: removedValues.UnsortedList(),
+ })
+ }
+ }
+ }
+ return removedCapabilities
+}
diff --git a/plugin/pkg/global/resourcereferencemanager/admission_test.go b/plugin/pkg/global/resourcereferencemanager/admission_test.go
index 8f85efc8b27..345091ad47e 100644
--- a/plugin/pkg/global/resourcereferencemanager/admission_test.go
+++ b/plugin/pkg/global/resourcereferencemanager/admission_test.go
@@ -3001,6 +3001,238 @@ var _ = Describe("resourcereferencemanager", func() {
})
})
+ Context("CloudProfile - Remove MachineCapabilities", func() {
+ var (
+ ctx context.Context
+ cloudProfile, oldCloudProfile *core.CloudProfile
+ namespacedCloudProfile *gardencorev1beta1.NamespacedCloudProfile
+ )
+
+ BeforeEach(func() {
+ ctx = context.Background()
+
+ // Base CloudProfile with MachineCapabilities
+ cloudProfile = &core.CloudProfile{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: cloudProfileName,
+ },
+ Spec: core.CloudProfileSpec{
+ MachineCapabilities: []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"amd64", "arm64"}},
+ {Name: "network", Values: []string{"public", "private"}},
+ {Name: "storage", Values: []string{"ssd", "hdd"}},
+ },
+ MachineImages: []core.MachineImage{
+ {
+ Name: "ubuntu",
+ Versions: []core.MachineImageVersion{
+ {
+ ExpirableVersion: core.ExpirableVersion{Version: "20.04"},
+ CapabilityFlavors: []core.MachineImageFlavor{
+ {Capabilities: core.Capabilities{
+ "architecture": []string{"amd64"},
+ "storage": []string{"ssd"},
+ }},
+ {Capabilities: core.Capabilities{
+ "architecture": []string{"amd64"},
+ "storage": []string{"ssd"},
+ }},
+ },
+ },
+ },
+ },
+ },
+ MachineTypes: []core.MachineType{
+ {
+ Name: "m5.large",
+ Capabilities: core.Capabilities{
+ "architecture": []string{"amd64"},
+ "network": []string{"public"},
+ },
+ },
+ },
+ },
+ }
+ oldCloudProfile = cloudProfile.DeepCopy()
+
+ // NamespacedCloudProfile that uses capabilities from parent
+ namespacedCloudProfile = &gardencorev1beta1.NamespacedCloudProfile{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "namespaced-profile",
+ Namespace: namespace,
+ },
+ Spec: gardencorev1beta1.NamespacedCloudProfileSpec{
+ Parent: gardencorev1beta1.CloudProfileReference{
+ Kind: "CloudProfile",
+ Name: cloudProfileName,
+ },
+ MachineImages: []gardencorev1beta1.MachineImage{
+ {
+ Name: "debian",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "11"},
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{
+ {Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": []string{"arm64"},
+ "network": []string{"private"},
+ "storage": []string{"hdd"},
+ }},
+ },
+ },
+ },
+ },
+ },
+ MachineTypes: []gardencorev1beta1.MachineType{
+ {
+ Name: "t3.micro",
+ Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": []string{"arm64"},
+ "storage": []string{"ssd"},
+ },
+ },
+ },
+ },
+ }
+
+ Expect(gardenCoreInformerFactory.Core().V1beta1().NamespacedCloudProfiles().Informer().GetStore().Add(namespacedCloudProfile)).To(Succeed())
+ })
+
+ It("should reject removing capability values still in use by NamespacedCloudProfile machine image flavors and machine types", func() {
+ // Remove arm64 architecture and private network capabilities that are used by NamespacedCloudProfile
+ cloudProfile.Spec.MachineCapabilities = []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"amd64"}}, // removed arm64
+ {Name: "network", Values: []string{"public"}}, // removed private
+ {Name: "storage", Values: []string{"ssd"}}, // removed hdd
+ }
+
+ attrs := admission.NewAttributesRecord(cloudProfile, oldCloudProfile, core.Kind("CloudProfile").WithVersion("version"), "", cloudProfile.Name, core.Resource("cloudprofiles").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, defaultUserInfo)
+
+ err := admissionHandler.Validate(ctx, attrs, nil)
+ Expect(err).To(HaveOccurred())
+
+ // Should get multiple errors for different capability values being removed
+ Expect(err.Error()).To(And(
+ ContainSubstring("unable to delete MachineCapability \"architecture\" with value \"arm64\" from CloudProfile"),
+ ContainSubstring("capability value is still in use by NamespacedCloudProfile 'default/namespaced-profile'"),
+ ContainSubstring("unable to delete MachineCapability \"network\" with value \"private\" from CloudProfile"),
+ ContainSubstring("unable to delete MachineCapability \"storage\" with value \"hdd\" from CloudProfile"),
+ ))
+ })
+
+ It("should allow removing capability values not used by any NamespacedCloudProfile", func() {
+ // Create another NamespacedCloudProfile that doesn't use certain capabilities
+ anotherNamespacedCloudProfile := &gardencorev1beta1.NamespacedCloudProfile{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "another-profile",
+ Namespace: namespace,
+ },
+ Spec: gardencorev1beta1.NamespacedCloudProfileSpec{
+ Parent: gardencorev1beta1.CloudProfileReference{
+ Kind: "CloudProfile",
+ Name: cloudProfileName,
+ },
+ MachineImages: []gardencorev1beta1.MachineImage{
+ {
+ Name: "centos",
+ Versions: []gardencorev1beta1.MachineImageVersion{
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "8"},
+ CapabilityFlavors: []gardencorev1beta1.MachineImageFlavor{
+ {Capabilities: gardencorev1beta1.Capabilities{
+ "architecture": []string{"amd64"}, // only uses amd64
+ "network": []string{"public"}, // only uses public
+ "storage": []string{"ssd"}, // only uses ssd
+ }},
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ Expect(gardenCoreInformerFactory.Core().V1beta1().NamespacedCloudProfiles().Informer().GetStore().Add(anotherNamespacedCloudProfile)).To(Succeed())
+
+ // This should succeed since the removed capabilities are not used by the additional NamespacedCloudProfile
+ // but will still fail due to the first NamespacedCloudProfile
+ cloudProfile.Spec.MachineCapabilities = []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"amd64"}}, // removed arm64 - still used by first profile
+ {Name: "network", Values: []string{"public"}}, // removed private - still used by first profile
+ {Name: "storage", Values: []string{"ssd"}}, // removed hdd - still used by first profile
+ }
+
+ attrs := admission.NewAttributesRecord(cloudProfile, oldCloudProfile, core.Kind("CloudProfile").WithVersion("version"), "", cloudProfile.Name, core.Resource("cloudprofiles").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, defaultUserInfo)
+
+ err := admissionHandler.Validate(ctx, attrs, nil)
+ Expect(err).To(HaveOccurred())
+ Expect(err.Error()).To(ContainSubstring("namespaced-profile")) // should reference the first profile that uses the removed capabilities
+ Expect(err.Error()).NotTo(ContainSubstring("another-profile")) // should not reference the second profile
+
+ // Now remove the deleted capabilities from the first NamespacedCloudProfile to allow the update
+ namespacedCloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors[0].Capabilities["architecture"] = []string{"amd64"}
+ namespacedCloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors[0].Capabilities["network"] = []string{"public"}
+ namespacedCloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors[0].Capabilities["storage"] = []string{"ssd"}
+ namespacedCloudProfile.Spec.MachineTypes[0].Capabilities["architecture"] = []string{"amd64"}
+ namespacedCloudProfile.Spec.MachineTypes[0].Capabilities["storage"] = []string{"ssd"}
+
+ Expect(gardenCoreInformerFactory.Core().V1beta1().NamespacedCloudProfiles().Informer().GetStore().Update(namespacedCloudProfile)).To(Succeed())
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
+ })
+
+ It("should reject completely removing capability definitions still in use", func() {
+ // Completely remove the storage capability definition
+ cloudProfile.Spec.MachineCapabilities = []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"amd64", "arm64"}},
+ {Name: "network", Values: []string{"public", "private"}},
+ // storage capability completely removed
+ }
+
+ attrs := admission.NewAttributesRecord(cloudProfile, oldCloudProfile, core.Kind("CloudProfile").WithVersion("version"), "", cloudProfile.Name, core.Resource("cloudprofiles").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, defaultUserInfo)
+
+ err := admissionHandler.Validate(ctx, attrs, nil)
+ Expect(err).To(HaveOccurred())
+ Expect(err.Error()).To(And(
+ ContainSubstring("unable to delete MachineCapability \"storage\""),
+ ContainSubstring("capability value is still in use by NamespacedCloudProfile 'default/namespaced-profile'"),
+ ))
+ })
+
+ It("should allow updates when NamespacedCloudProfile has deletion timestamp", func() {
+ // Mark NamespacedCloudProfile for deletion
+ deletionTime := metav1.Now()
+ namespacedCloudProfile.DeletionTimestamp = &deletionTime
+
+ Expect(gardenCoreInformerFactory.Core().V1beta1().NamespacedCloudProfiles().Informer().GetStore().Update(namespacedCloudProfile)).To(Succeed())
+
+ // Now removing capabilities should succeed since the NamespacedCloudProfile is being deleted
+ cloudProfile.Spec.MachineCapabilities = []core.CapabilityDefinition{
+ // removed network and storage capabilities
+ {Name: "architecture", Values: []string{"amd64"}}, // removed arm64
+ }
+
+ attrs := admission.NewAttributesRecord(cloudProfile, oldCloudProfile, core.Kind("CloudProfile").WithVersion("version"), "", cloudProfile.Name, core.Resource("cloudprofiles").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, defaultUserInfo)
+
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
+ })
+
+ It("should allow updates when NamespacedCloudProfile references different parent", func() {
+ // Make NamespacedCloudProfile reference a different CloudProfile
+ namespacedCloudProfile.Spec.Parent.Name = "different-parent"
+
+ Expect(gardenCoreInformerFactory.Core().V1beta1().NamespacedCloudProfiles().Informer().GetStore().Update(namespacedCloudProfile)).To(Succeed())
+
+ // Now removing capabilities should succeed since the NamespacedCloudProfile doesn't reference this CloudProfile
+ cloudProfile.Spec.MachineCapabilities = []core.CapabilityDefinition{
+ {Name: "architecture", Values: []string{"amd64"}}, // removed arm64
+ }
+
+ attrs := admission.NewAttributesRecord(cloudProfile, oldCloudProfile, core.Kind("CloudProfile").WithVersion("version"), "", cloudProfile.Name, core.Resource("cloudprofiles").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, defaultUserInfo)
+
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
+ })
+ })
+
Context("NamespacedCloudProfile - Extending Kubernetes versions", func() {
var (
expirationDateFuture2 metav1.Time
diff --git a/plugin/pkg/namespacedcloudprofile/validator/admission.go b/plugin/pkg/namespacedcloudprofile/validator/admission.go
index 0b9ef80a6eb..d1b3148f95f 100644
--- a/plugin/pkg/namespacedcloudprofile/validator/admission.go
+++ b/plugin/pkg/namespacedcloudprofile/validator/admission.go
@@ -12,11 +12,12 @@ import (
"reflect"
apierrors "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/admission"
"k8s.io/utils/ptr"
- "github.com/gardener/gardener/pkg/api"
+ gardencoreapi "github.com/gardener/gardener/pkg/api"
gardencore "github.com/gardener/gardener/pkg/apis/core"
gardencorehelper "github.com/gardener/gardener/pkg/apis/core/helper"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
@@ -137,6 +138,10 @@ func (v *ValidateNamespacedCloudProfile) Validate(ctx context.Context, a admissi
return apierrors.NewBadRequest("parent CloudProfile could not be found")
}
+ if err := v.simulateTransformationToParentSpecFormat(namespacedCloudProfile, parentCloudProfile, oldNamespacedCloudProfile); err != nil {
+ return err
+ }
+
validationContext := &validationContext{
parentCloudProfile: parentCloudProfile,
namespacedCloudProfile: namespacedCloudProfile,
@@ -159,6 +164,30 @@ func (v *ValidateNamespacedCloudProfile) Validate(ctx context.Context, a admissi
return nil
}
+// TODO(Roncossek): Remove simulateTransformationToParentSpecFormat once all CloudProfiles have been migrated to use CapabilityFlavors and the Architecture fields are effectively forbidden or have been removed.
+func (v *ValidateNamespacedCloudProfile) simulateTransformationToParentSpecFormat(namespacedCloudProfile *gardencore.NamespacedCloudProfile, parentCloudProfile *gardencorev1beta1.CloudProfile, oldNamespacedCloudProfile *gardencore.NamespacedCloudProfile) error {
+ var namespacedCloudProfileSpecV1beta1 gardencorev1beta1.NamespacedCloudProfileSpec
+ if err := gardencoreapi.Scheme.Convert(&namespacedCloudProfile.Spec, &namespacedCloudProfileSpecV1beta1, nil); err != nil {
+ return apierrors.NewInternalError(err)
+ }
+ // simulate status transformation if namespaced cloud profile controller would do it
+ uniformNamespacedCloudProfileSpec := gardenerutils.TransformSpecToParentFormat(namespacedCloudProfileSpecV1beta1, parentCloudProfile.Spec.MachineCapabilities)
+ if err := gardencoreapi.Scheme.Convert(&uniformNamespacedCloudProfileSpec, &namespacedCloudProfile.Spec, nil); err != nil {
+ return apierrors.NewInternalError(err)
+ }
+
+ var oldNamespacedCloudProfileSpecV1beta1 gardencorev1beta1.NamespacedCloudProfileSpec
+ if err := gardencoreapi.Scheme.Convert(&oldNamespacedCloudProfile.Spec, &oldNamespacedCloudProfileSpecV1beta1, nil); err != nil {
+ return apierrors.NewInternalError(err)
+ }
+ // simulate status transformation if namespaced cloud profile controller would do it
+ oldUniformNamespacedCloudProfileSpec := gardenerutils.TransformSpecToParentFormat(oldNamespacedCloudProfileSpecV1beta1, parentCloudProfile.Spec.MachineCapabilities)
+ if err := gardencoreapi.Scheme.Convert(&oldUniformNamespacedCloudProfileSpec, &oldNamespacedCloudProfile.Spec, nil); err != nil {
+ return apierrors.NewInternalError(err)
+ }
+ return nil
+}
+
type validationContext struct {
parentCloudProfile *gardencorev1beta1.CloudProfile
namespacedCloudProfile *gardencore.NamespacedCloudProfile
@@ -235,11 +264,16 @@ func (c *validationContext) validateMachineImageOverrides(ctx context.Context, a
oldVersionsMerged = gardenerutils.NewCoreImagesContext(c.oldNamespacedCloudProfile.Status.CloudProfileSpec.MachineImages)
}
+ var parentCloudProfileSpecCore gardencore.CloudProfileSpec
+ if err := gardencoreapi.Scheme.Convert(&c.parentCloudProfile.Spec, &parentCloudProfileSpecCore, ctx); err != nil {
+ return apierrors.NewInternalError(err)
+ }
+ capabilities := gardencorehelper.CapabilityDefinitionsToCapabilities(parentCloudProfileSpecCore.MachineCapabilities)
+
for imageIndex, image := range c.namespacedCloudProfile.Spec.MachineImages {
imageIndexPath := field.NewPath("spec", "machineImages").Index(imageIndex)
- _, isExistingImage := parentImages.GetImage(image.Name)
-
- if isExistingImage {
+ _, imageExistsInParent := parentImages.GetImage(image.Name)
+ if imageExistsInParent {
// If in the meantime an image specified only in the NamespacedCloudProfile has been
// added to the parent CloudProfile, then ignore already existing fields otherwise invalid for a new override.
var imageAlreadyExistsInNamespacedCloudProfile bool
@@ -253,11 +287,11 @@ func (c *validationContext) validateMachineImageOverrides(ctx context.Context, a
}
for imageVersionIndex, imageVersion := range image.Versions {
+ imageVersionIndexPath := imageIndexPath.Child("versions").Index(imageVersionIndex)
if _, isExistingVersion := parentImages.GetImageVersion(image.Name, imageVersion.Version); isExistingVersion {
// An image with the specified version is already present in the parent CloudProfile.
// Ensure that only the expiration date is overridden.
// For new versions added to an existing image, the validation will be done on the simulated merge result.
- imageVersionIndexPath := imageIndexPath.Child("versions").Index(imageVersionIndex)
// If in the meantime an image version specified only in the NamespacedCloudProfile has been
// added to the parent CloudProfile, then ignore already existing fields otherwise invalid for a new override.
@@ -291,18 +325,17 @@ func (c *validationContext) validateMachineImageOverrides(ctx context.Context, a
allErrs = append(allErrs, field.Invalid(imageVersionIndexPath.Child("expirationDate"), imageVersion.ExpirationDate, fmt.Sprintf("expiration date for version %q is in the past", imageVersion.Version)))
}
}
+ } else {
+ // New image version added to an existing image.
+ allErrs = append(allErrs, validation.ValidateMachineImageVersion(image, imageVersion, capabilities, sets.Set[string]{}, imageVersionIndexPath)...)
}
}
} else {
- var parentCloudProfileSpecCore gardencore.CloudProfileSpec
- if err := api.Scheme.Convert(&c.parentCloudProfile.Spec, &parentCloudProfileSpecCore, ctx); err != nil {
- allErrs = append(allErrs, field.InternalError(imageIndexPath, err))
+ allErrs = append(allErrs, validation.ValidateMachineImage(image, capabilities, sets.Set[string]{}, sets.Set[string]{}, false, imageIndexPath)...)
+ for index, machineVersion := range image.Versions {
+ versionsPath := imageIndexPath.Child("versions").Index(index)
+ allErrs = append(allErrs, validation.ValidateMachineImageAdditionalConfig(machineVersion, versionsPath, image, capabilities)...)
}
-
- // There is no entry for this image in the parent CloudProfile yet.
- capabilities := gardencorehelper.CapabilityDefinitionsToCapabilities(parentCloudProfileSpecCore.MachineCapabilities)
- allErrs = append(allErrs, validation.ValidateMachineImages([]gardencore.MachineImage{image}, capabilities, imageIndexPath, false)...)
- allErrs = append(allErrs, validation.ValidateCloudProfileMachineImages([]gardencore.MachineImage{image}, capabilities, imageIndexPath)...)
}
}
return allErrs.ToAggregate()
@@ -335,7 +368,7 @@ func validateNamespacedCloudProfileExtendedMachineImages(machineVersion gardenco
func (c *validationContext) validateSimulatedCloudProfileStatusMergeResult() error {
namespacedCloudProfile := &gardencorev1beta1.NamespacedCloudProfile{}
- if err := api.Scheme.Convert(c.namespacedCloudProfile, namespacedCloudProfile, nil); err != nil {
+ if err := gardencoreapi.Scheme.Convert(c.namespacedCloudProfile, namespacedCloudProfile, nil); err != nil {
return err
}
errs := ValidateSimulatedNamespacedCloudProfileStatus(c.parentCloudProfile, namespacedCloudProfile)
@@ -354,7 +387,7 @@ func ValidateSimulatedNamespacedCloudProfileStatus(originalParentCloudProfile *g
namespacedcloudprofile.MergeCloudProfiles(namespacedCloudProfile, parentCloudProfile)
coreNamespacedCloudProfile := &gardencore.NamespacedCloudProfile{}
- if err := api.Scheme.Convert(namespacedCloudProfile, coreNamespacedCloudProfile, nil); err != nil {
+ if err := gardencoreapi.Scheme.Convert(namespacedCloudProfile, coreNamespacedCloudProfile, nil); err != nil {
return field.ErrorList{{
Type: field.ErrorTypeInternal,
Field: "",
diff --git a/plugin/pkg/namespacedcloudprofile/validator/admission_test.go b/plugin/pkg/namespacedcloudprofile/validator/admission_test.go
index d97b466405e..8ecc93e7475 100644
--- a/plugin/pkg/namespacedcloudprofile/validator/admission_test.go
+++ b/plugin/pkg/namespacedcloudprofile/validator/admission_test.go
@@ -11,6 +11,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gstruct"
+ "github.com/onsi/gomega/types"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
@@ -126,80 +127,129 @@ var _ = Describe("Admission", func() {
})
Describe("Adding machineImage Versions and machineTypes NOT defined in the parent CloudProfile", func() {
- BeforeEach(func() {
- namespacedCloudProfile.Spec.MachineImages = []gardencore.MachineImage{
- {
- Name: "test-image",
- Versions: []gardencore.MachineImageVersion{{
- ExpirableVersion: gardencore.ExpirableVersion{Version: "1.0.1"},
- CRI: []gardencore.CRI{{Name: "containerd"}},
- }}}}
- })
-
- It("should allow adding a machineImage without Capabilities as architecture defaults to amd64", func() {
- Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
- attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
- Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
- })
-
- It("should reject a machineImage with Capabilities or CapabilityValues not in the parent CloudProfile", func() {
- Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
- namespacedCloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = []gardencore.MachineImageFlavor{
- {Capabilities: gardencore.Capabilities{
- // Unsupported CapabilityValue
- "capability2": []string{"value3"},
- // Unsupported Capability
- "not-in-parent": []string{"value1", "value2"}}},
- }
-
- attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
- Expect(admissionHandler.Validate(ctx, attrs, nil)).To(MatchError(And(
- ContainSubstring(`capability2[0]: Unsupported value: "value3": supported values: "value1", "value2"`),
- ContainSubstring(`Unsupported value: "not-in-parent": supported values:`),
- )))
- })
-
- It("should allow machineTypes and overwrite Architecture if it conflicts with Capabilities.Architecture", func() {
- Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
-
- namespacedCloudProfile.Spec.MachineTypes = []gardencore.MachineType{{Name: "my-other-machine",
- Architecture: ptr.To("amd64"),
- Capabilities: gardencore.Capabilities{constants.ArchitectureName: []string{"arm64"}},
- }}
-
- attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
-
- Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
+ When("Architecture capability has one supported value", func() {
+ BeforeEach(func() {
+ parentCloudProfile.Spec.MachineCapabilities = []gardencorev1beta1.CapabilityDefinition{
+ {Name: constants.ArchitectureName, Values: []string{"amd64"}},
+ {Name: "capability2", Values: []string{"value1", "value2"}},
+ }
+ namespacedCloudProfile.Spec.MachineImages = []gardencore.MachineImage{
+ {
+ Name: "test-image",
+ Versions: []gardencore.MachineImageVersion{{
+ ExpirableVersion: gardencore.ExpirableVersion{Version: "1.0.1"},
+ CRI: []gardencore.CRI{{Name: "containerd"}},
+ }}}}
+ })
+
+ It("should allow adding a machineImage without Capabilities as architecture defaults from capabilityDefinition", func() {
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
+ attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
+ })
+
+ It("should allow machineTypes without Capabilities as architecture defaults to capabilityDefinition", func() {
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
+ namespacedCloudProfile.Spec.MachineTypes = []gardencore.MachineType{{Name: "my-other-machine"}}
+
+ attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
+
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
+ })
})
- It("should reject unsupported Capabilities or CapabilityValues in machineTypes", func() {
- Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
-
- namespacedCloudProfile.Spec.MachineTypes = []gardencore.MachineType{{Name: "my-other-machine",
- Capabilities: gardencore.Capabilities{constants.ArchitectureName: []string{"arm64"},
- // Unsupported CapabilityValue
- "capability2": []string{"value3"},
- // Unsupported Capability
- "not-in-parent": []string{"value1", "value2"}},
- }}
-
- attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
-
- Expect(admissionHandler.Validate(ctx, attrs, nil)).To(MatchError(And(
- ContainSubstring(`capability2[0]: Unsupported value: "value3": supported values: "value1", "value2"`),
- ContainSubstring(`Unsupported value: "not-in-parent": supported values:`),
- )))
+ When("Architecture capability has multiple supported values", func() {
+ BeforeEach(func() {
+ parentCloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = []gardencorev1beta1.MachineImageFlavor{
+ {Capabilities: gardencorev1beta1.Capabilities{constants.ArchitectureName: []string{"amd64"}}},
+ }
+ namespacedCloudProfile.Spec.MachineImages = []gardencore.MachineImage{
+ {
+ Name: "test-image",
+ Versions: []gardencore.MachineImageVersion{{
+ ExpirableVersion: gardencore.ExpirableVersion{Version: "1.0.1"},
+ CRI: []gardencore.CRI{{Name: "containerd"}},
+ CapabilityFlavors: []gardencore.MachineImageFlavor{{
+ Capabilities: gardencore.Capabilities{constants.ArchitectureName: []string{"amd64"}},
+ }},
+ }}}}
+ })
+
+ It("should allow adding a machineImage with Capabilities", func() {
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
+ namespacedCloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = []gardencore.MachineImageFlavor{
+ {Capabilities: gardencore.Capabilities{"architecture": []string{"arm64"}}},
+ }
+ attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(Succeed())
+ })
+
+ It("should reject a machineImage with Capabilities or CapabilityValues not in the parent CloudProfile", func() {
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
+ namespacedCloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = []gardencore.MachineImageFlavor{
+ {Capabilities: gardencore.Capabilities{
+ // Unsupported CapabilityValue
+ "capability2": []string{"value3"},
+ // Unsupported Capability
+ "not-in-parent": []string{"value1", "value2"}}},
+ }
+
+ attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(MatchError(And(
+ ContainSubstring(`capability2[0]: Unsupported value: "value3": supported values: "value1", "value2"`),
+ ContainSubstring(`Unsupported value: "not-in-parent": supported values:`),
+ )))
+ })
+
+ It("should reject machineTypes if it conflicts with Capabilities.Architecture", func() {
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
+ namespacedCloudProfile.Spec.MachineImages = []gardencore.MachineImage{}
+
+ namespacedCloudProfile.Spec.MachineTypes = []gardencore.MachineType{{Name: "my-other-machine",
+ Architecture: ptr.To("amd64"),
+ Capabilities: gardencore.Capabilities{constants.ArchitectureName: []string{"arm64"}},
+ }}
+
+ attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
+
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(MatchError(And(
+ ContainSubstring("status.cloudProfileSpec.machineTypes[0].architecture"),
+ ContainSubstring("machine type architecture (amd64) conflicts with the capability architecture (arm64)"),
+ )))
+ })
+
+ It("should reject unsupported Capabilities or CapabilityValues in machineTypes", func() {
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(parentCloudProfile)).To(Succeed())
+ namespacedCloudProfile.Spec.MachineTypes = []gardencore.MachineType{{Name: "my-other-machine",
+ Capabilities: gardencore.Capabilities{
+ constants.ArchitectureName: []string{"arm64"},
+ // Unsupported CapabilityValue
+ "capability2": []string{"value3"},
+ // Unsupported Capability
+ "not-in-parent": []string{"value1", "value2"}},
+ }}
+
+ attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
+
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(MatchError(And(
+ ContainSubstring(`capability2[0]: Unsupported value: "value3": supported values: "value1", "value2"`),
+ ContainSubstring(`Unsupported value: "not-in-parent": supported values:`),
+ )))
+ })
})
})
Describe("Adding machineImages defined in the parent CloudProfile", func() {
BeforeEach(func() {
- namespacedCloudProfile.Spec.MachineImages = []gardencore.MachineImage{
- {
- Name: "test-image",
- Versions: []gardencore.MachineImageVersion{{
- ExpirableVersion: gardencore.ExpirableVersion{Version: "1.0.0", ExpirationDate: validExpirationDate},
- }}}}
+ parentCloudProfile.Spec.MachineImages[0].Versions[0].CapabilityFlavors = []gardencorev1beta1.MachineImageFlavor{{
+ Capabilities: gardencorev1beta1.Capabilities{constants.ArchitectureName: []string{"amd64"}},
+ }}
+ namespacedCloudProfile.Spec.MachineImages = []gardencore.MachineImage{{
+ Name: "test-image",
+ Versions: []gardencore.MachineImageVersion{{
+ ExpirableVersion: gardencore.ExpirableVersion{Version: "1.0.0", ExpirationDate: validExpirationDate},
+ }},
+ }}
})
It("should allow to add a machineImage without Capabilities", func() {
@@ -514,7 +564,20 @@ var _ = Describe("Admission", func() {
Expect(admissionHandler.Validate(ctx, attrs, nil)).To(MatchError(ContainSubstring("expiration date for version \"1.0.0\" must be set")))
})
- It("should fail for creating a NamespacedCloudProfile that overrides an existing MachineImage version and specifies classification/cri/arch/flavors/kubeletVersionConstraint/inPlaceUpdates", func() {
+ DescribeTable("should fail for creating a NamespacedCloudProfile that overrides an existing MachineImage version and specifies classification/cri/arch/flavors/kubeletVersionConstraint/inPlaceUpdates", func(parentUsesCapabilities bool) {
+ var additionalMatcher types.GomegaMatcher
+ if parentUsesCapabilities {
+ parentCloudProfile.Spec.MachineCapabilities = []gardencorev1beta1.CapabilityDefinition{{
+ Name: "architecture",
+ Values: []string{"amd64", "arm64"},
+ }}
+ // capabilityFlavors will be deleted on transform in transformation to parent format
+ additionalMatcher = PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeForbidden),
+ "Field": Equal("spec.machineImages[0].versions[0].capabilityFlavors"),
+ "Detail": ContainSubstring("must not provide capabilities to an extended machine image in NamespacedCloudProfile"),
+ }))
+ }
parentCloudProfile.Spec.MachineImages = []gardencorev1beta1.MachineImage{
{Name: "test-image", Versions: []gardencorev1beta1.MachineImageVersion{
{ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "1.1.0"}, CRI: []gardencorev1beta1.CRI{{Name: "containerd"}}},
@@ -539,7 +602,7 @@ var _ = Describe("Admission", func() {
attrs := admission.NewAttributesRecord(namespacedCloudProfile, nil, gardencorev1beta1.Kind("NamespacedCloudProfile").WithVersion("version"), "", namespacedCloudProfile.Name, gardencorev1beta1.Resource("namespacedcloudprofile").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
- Expect(admissionHandler.Validate(ctx, attrs, nil)).To(ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{
+ matchers := []types.GomegaMatcher{PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeForbidden),
"Field": Equal("spec.machineImages[0].versions[0].cri"),
"Detail": ContainSubstring("must not provide a cri to an extended machine image in NamespacedCloudProfile"),
@@ -547,14 +610,6 @@ var _ = Describe("Admission", func() {
"Type": Equal(field.ErrorTypeForbidden),
"Field": Equal("spec.machineImages[0].versions[0].classification"),
"Detail": ContainSubstring("must not provide a classification to an extended machine image in NamespacedCloudProfile"),
- })), PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeForbidden),
- "Field": Equal("spec.machineImages[0].versions[0].architectures"),
- "Detail": ContainSubstring("must not provide an architecture to an extended machine image in NamespacedCloudProfile"),
- })), PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeForbidden),
- "Field": Equal("spec.machineImages[0].versions[0].capabilityFlavors"),
- "Detail": ContainSubstring("must not provide capabilities to an extended machine image in NamespacedCloudProfile"),
})), PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeForbidden),
"Field": Equal("spec.machineImages[0].versions[0].kubeletVersionConstraint"),
@@ -563,8 +618,20 @@ var _ = Describe("Admission", func() {
"Type": Equal(field.ErrorTypeForbidden),
"Field": Equal("spec.machineImages[0].versions[0].inPlaceUpdates"),
"Detail": ContainSubstring("must not provide inPlaceUpdates to an extended machine image in NamespacedCloudProfile"),
- }))))
- })
+ })), PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeForbidden),
+ "Field": Equal("spec.machineImages[0].versions[0].architectures"),
+ "Detail": ContainSubstring("must not provide an architecture to an extended machine image in NamespacedCloudProfile"),
+ }))}
+
+ if parentUsesCapabilities {
+ matchers = append(matchers, additionalMatcher)
+ }
+ Expect(admissionHandler.Validate(ctx, attrs, nil)).To(ConsistOf(matchers))
+ },
+ Entry("parent without capabilities", false),
+ Entry("parent with capabilities", true),
+ )
It("should fail for updating a NamespacedCloudProfile that specifies an already expired MachineImage version", func() {
parentCloudProfile.Spec.MachineImages = []gardencorev1beta1.MachineImage{
diff --git a/plugin/pkg/shoot/validator/admission.go b/plugin/pkg/shoot/validator/admission.go
index a1d2c3a71fe..7bd770a22da 100644
--- a/plugin/pkg/shoot/validator/admission.go
+++ b/plugin/pkg/shoot/validator/admission.go
@@ -1078,7 +1078,7 @@ func (c *validationContext) validateMachineImage(idxPath *field.Path, worker cor
isUpdateStrategyInPlace := helper.IsUpdateStrategyInPlace(worker.UpdateStrategy)
isMachineImagePresentInCloudprofile, architectureSupported, activeMachineImageVersion, inPlaceUpdateSupported, validMachineImageVersions := validateMachineImagesConstraints(a, c.cloudProfileSpec.MachineImages, isNewWorkerPool, isUpdateStrategyInPlace, worker.Machine, oldWorker.Machine, c.cloudProfileSpec.MachineCapabilities)
if !isMachineImagePresentInCloudprofile {
- return field.Invalid(idxPath.Child("machine", "image"), worker.Machine.Image, fmt.Sprintf("machine image version is not supported, supported machine image versions are: %+v", validMachineImageVersions))
+ return field.NotSupported(idxPath.Child("machine", "image", "version"), worker.Machine.Image.Version, validMachineImageVersions)
}
if !architectureSupported || !activeMachineImageVersion || (isUpdateStrategyInPlace && !inPlaceUpdateSupported) {
diff --git a/plugin/pkg/shoot/validator/admission_test.go b/plugin/pkg/shoot/validator/admission_test.go
index 42c64e7c8b3..92975828121 100644
--- a/plugin/pkg/shoot/validator/admission_test.go
+++ b/plugin/pkg/shoot/validator/admission_test.go
@@ -4135,7 +4135,7 @@ var _ = Describe("validator", func() {
attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
err := admissionHandler.Admit(ctx, attrs, nil)
- Expect(err).To(MatchError(ContainSubstring("machine image version is not supported")))
+ Expect(err).To(MatchError(ContainSubstring("Unsupported value: \"1.2.baz\": supported values:")))
})
It("should default a machine image version to latest major.minor.patch version", func() {
diff --git a/skaffold-operator.yaml b/skaffold-operator.yaml
index e1fa4e58cdd..234857b7643 100644
--- a/skaffold-operator.yaml
+++ b/skaffold-operator.yaml
@@ -1248,6 +1248,8 @@ build:
- extensions/pkg/apis/config/v1alpha1
- extensions/pkg/controller
- extensions/pkg/controller/cmd
+ - extensions/pkg/controller/worker
+ - extensions/pkg/predicate
- extensions/pkg/util
- extensions/pkg/webhook
- extensions/pkg/webhook/certificates
@@ -1291,7 +1293,9 @@ build:
- pkg/client/kubernetes
- pkg/client/kubernetes/cache
- pkg/controllerutils
+ - pkg/controllerutils/mapper
- pkg/controllerutils/predicate
+ - pkg/controllerutils/reconciler
- pkg/extensions
- pkg/gardenlet/apis/config/v1alpha1
- pkg/healthz
@@ -1301,6 +1305,7 @@ build:
- pkg/provider-local/admission/mutator
- pkg/provider-local/admission/validator
- pkg/provider-local/apis/local
+ - pkg/provider-local/apis/local/helper
- pkg/provider-local/apis/local/install
- pkg/provider-local/apis/local/v1alpha1
- pkg/provider-local/apis/local/validation
@@ -1313,6 +1318,7 @@ build:
- pkg/utils/flow
- pkg/utils/gardener
- pkg/utils/gardener/operator
+ - pkg/utils/gardener/shootstate
- pkg/utils/imagevector
- pkg/utils/kubernetes
- pkg/utils/kubernetes/health
diff --git a/test/integration/controllermanager/namespacedcloudprofile/namespacedcloudprofile_test.go b/test/integration/controllermanager/namespacedcloudprofile/namespacedcloudprofile_test.go
index 05ae99ddd34..ca00e11b576 100644
--- a/test/integration/controllermanager/namespacedcloudprofile/namespacedcloudprofile_test.go
+++ b/test/integration/controllermanager/namespacedcloudprofile/namespacedcloudprofile_test.go
@@ -18,7 +18,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
- v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
"github.com/gardener/gardener/pkg/features"
"github.com/gardener/gardener/pkg/utils/test"
. "github.com/gardener/gardener/pkg/utils/test/matchers"
@@ -33,6 +32,7 @@ var _ = DescribeTableSubtree("NamespacedCloudProfile controller tests", func(isC
expirationDateFuture metav1.Time
imageFlavors []gardencorev1beta1.MachineImageFlavor
+ capabilities gardencorev1beta1.Capabilities
)
BeforeEach(func() {
@@ -40,14 +40,12 @@ var _ = DescribeTableSubtree("NamespacedCloudProfile controller tests", func(isC
var capabilityDefinitions []gardencorev1beta1.CapabilityDefinition
if isCapabilitiesCloudProfile {
capabilityDefinitions = []gardencorev1beta1.CapabilityDefinition{
- {
- Name: "architecture",
- Values: []string{v1beta1constants.ArchitectureAMD64},
- },
+ {Name: "architecture", Values: []string{"amd64"}},
}
imageFlavors = []gardencorev1beta1.MachineImageFlavor{
- {Capabilities: gardencorev1beta1.Capabilities{"architecture": []string{v1beta1constants.ArchitectureAMD64}}},
+ {Capabilities: gardencorev1beta1.Capabilities{"architecture": []string{"amd64"}}},
}
+ capabilities = gardencorev1beta1.Capabilities{"architecture": []string{"amd64"}}
}
dateNow, _ := time.Parse(time.DateOnly, time.Now().Format(time.DateOnly))
@@ -69,10 +67,7 @@ var _ = DescribeTableSubtree("NamespacedCloudProfile controller tests", func(isC
{
Name: "some-image",
Versions: []gardencorev1beta1.MachineImageVersion{
- {
- ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "4.5.6"},
- CapabilityFlavors: imageFlavors,
- },
+ {ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "4.5.6"}},
},
},
},
@@ -103,13 +98,19 @@ var _ = DescribeTableSubtree("NamespacedCloudProfile controller tests", func(isC
Name: "some-image",
Versions: []gardencorev1beta1.MachineImageVersion{
{ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "4.5.6", ExpirationDate: &expirationDateFuture}},
- {ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "7.8.9"}, CRI: []gardencorev1beta1.CRI{{Name: "containerd"}}, Architectures: []string{"amd64"}, CapabilityFlavors: imageFlavors},
+ {ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "7.8.9"}, CRI: []gardencorev1beta1.CRI{{Name: "containerd"}}}, // no capabilities defined, as spec.MachineCapabilities will be used
},
},
{
Name: "custom-image",
Versions: []gardencorev1beta1.MachineImageVersion{
- {ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "1.1.2"}, CRI: []gardencorev1beta1.CRI{{Name: "containerd"}}, Architectures: []string{"amd64"}, CapabilityFlavors: imageFlavors},
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "1.1.2"},
+ CRI: []gardencorev1beta1.CRI{{Name: "containerd"}},
+ Architectures: []string{"amd64"},
+ // explicitly define capabilities 1.1.2 is not in parent cloudprofile
+ CapabilityFlavors: imageFlavors,
+ },
},
UpdateStrategy: &updateStrategy,
},
@@ -142,15 +143,14 @@ var _ = DescribeTableSubtree("NamespacedCloudProfile controller tests", func(isC
Name: "some-image",
Versions: []gardencorev1beta1.MachineImageVersion{
{
- ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "7.8.9"},
- CRI: []gardencorev1beta1.CRI{{Name: "containerd"}},
- Architectures: []string{"amd64"},
- CapabilityFlavors: imageFlavors,
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "7.8.9"},
+ CRI: []gardencorev1beta1.CRI{{Name: "containerd"}},
+ Architectures: []string{"amd64"},
},
{
ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "4.5.6", ExpirationDate: &expirationDateFuture},
- CRI: []gardencorev1beta1.CRI{{Name: "containerd", ContainerRuntimes: nil}}, Architectures: []string{"amd64"},
- CapabilityFlavors: imageFlavors,
+ CRI: []gardencorev1beta1.CRI{{Name: "containerd"}},
+ Architectures: []string{"amd64"},
},
},
UpdateStrategy: &updateStrategy,
@@ -183,6 +183,7 @@ var _ = DescribeTableSubtree("NamespacedCloudProfile controller tests", func(isC
Memory: resource.MustParse("2Gi"),
Usable: &usable,
Architecture: &architecture,
+ Capabilities: capabilities,
}},
Regions: []gardencorev1beta1.Region{
{Name: "some-region"},
@@ -541,7 +542,11 @@ var _ = DescribeTableSubtree("NamespacedCloudProfile controller tests", func(isC
{
Name: "some-image",
Versions: []gardencorev1beta1.MachineImageVersion{
- {ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "4.5.6", ExpirationDate: &expirationDatePast}},
+ {
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "4.5.6", ExpirationDate: &expirationDatePast},
+ Architectures: []string{"amd64"},
+ CapabilityFlavors: imageFlavors,
+ },
},
},
}
@@ -556,10 +561,9 @@ var _ = DescribeTableSubtree("NamespacedCloudProfile controller tests", func(isC
Name: "some-image",
Versions: []gardencorev1beta1.MachineImageVersion{
{
- ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "4.5.6"},
- CRI: []gardencorev1beta1.CRI{{Name: "containerd"}},
- Architectures: []string{"amd64"},
- CapabilityFlavors: imageFlavors,
+ ExpirableVersion: gardencorev1beta1.ExpirableVersion{Version: "4.5.6"},
+ CRI: []gardencorev1beta1.CRI{{Name: "containerd"}},
+ Architectures: []string{"amd64"},
},
},
UpdateStrategy: ptr.To(gardencorev1beta1.UpdateStrategyMajor),
From 0aa0905616fbfb12a220ee88ad859760554bde76 Mon Sep 17 00:00:00 2001
From: rhubenov
Date: Mon, 3 Nov 2025 16:00:21 +0200
Subject: [PATCH 019/176] Switch to using `matches` for config to include the
kernel logs (#13328)
---
.../components/opentelemetrycollector/config_test.go | 10 +++++-----
.../templates/opentelemetry-collector-config.yaml.tpl | 10 +++++-----
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/config_test.go b/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/config_test.go
index 7e087c3cceb..4cc55cf9c12 100644
--- a/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/config_test.go
+++ b/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/config_test.go
@@ -98,11 +98,11 @@ receivers:
journald/journal:
start_at: beginning
storage: file_storage
- units:
- - kernel
- - kubelet.service
- - containerd.service
- - gardener-node-agent.service
+ matches:
+ - _TRANSPORT: kernel
+ - _SYSTEMD_UNIT: kubelet.service
+ - _SYSTEMD_UNIT: containerd.service
+ - _SYSTEMD_UNIT: gardener-node-agent.service
operators:
- type: move
from: body._SYSTEMD_UNIT
diff --git a/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/templates/opentelemetry-collector-config.yaml.tpl b/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/templates/opentelemetry-collector-config.yaml.tpl
index 2cd0340da65..7a1c7c67eee 100644
--- a/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/templates/opentelemetry-collector-config.yaml.tpl
+++ b/pkg/component/extensions/operatingsystemconfig/original/components/opentelemetrycollector/templates/opentelemetry-collector-config.yaml.tpl
@@ -14,11 +14,11 @@ receivers:
journald/journal:
start_at: beginning
storage: file_storage
- units:
- - kernel
- - kubelet.service
- - containerd.service
- - gardener-node-agent.service
+ matches:
+ - _TRANSPORT: kernel
+ - _SYSTEMD_UNIT: kubelet.service
+ - _SYSTEMD_UNIT: containerd.service
+ - _SYSTEMD_UNIT: gardener-node-agent.service
operators:
- type: move
from: body._SYSTEMD_UNIT
From 7115486100ea6f78435695d7088a46c2481877e0 Mon Sep 17 00:00:00 2001
From: Sonu Kumar Singh
Date: Mon, 3 Nov 2025 20:20:11 +0530
Subject: [PATCH 020/176] Fix docs (#13331)
---
docs/deployment/setup_gardener.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/deployment/setup_gardener.md b/docs/deployment/setup_gardener.md
index 764119fc6eb..21f4b40588a 100644
--- a/docs/deployment/setup_gardener.md
+++ b/docs/deployment/setup_gardener.md
@@ -281,7 +281,7 @@ NAME K8S VERSION GARDENER VERSION LAST OPERATION RUNTIME VIRTUA
crazy-botany 1.31.1 v1.110.0 Succeeded True True True True 1d
```
-In case the automatic DNS record creation is not supported, a record with the external address of the `virtual-garden-istio-ingress` (found in namespace `istio-ingressgateway`) service has to be created manually.
+In case the automatic DNS record creation is not supported, a record with the external address of the `istio-ingressgateway` (found in namespace `virtual-garden-istio-ingress`) service has to be created manually.
To obtain credentials and interact with the virtual Garden cluster, please follow this [guide](../concepts/operator.md#virtual-garden-kubeconfig).
From 803429aafecde13526fcdaeef91bc155dff9f8e8 Mon Sep 17 00:00:00 2001
From: Tobias Schlicht <155947440+tobschli@users.noreply.github.com>
Date: Mon, 3 Nov 2025 18:08:12 +0100
Subject: [PATCH 021/176] Support for Kubernetes 1.34 (#12883)
* feat: Allow instantiating v1.34 Kubernetes clients
* docs: Update supported Kubernetes versions in docs
* docs: align docs with usage
* feat: Maintain feature gates for v1.34
./hack/compare-k8s-feature-gates.sh 1.33 1.34
Feature gates added in 1.34 compared to 1.33:
ClearingNominatedNodeNameAfterBinding
ContainerRestartRules
DRAConsumableCapacity
DRADeviceBindingConditions
DRAExtendedResource
DRASchedulerFilterTimeout
DetectCacheInconsistency
EnvFiles
HostnameOverride
InPlacePodVerticalScalingExclusiveMemory
KubeletPodResourcesListUseActivePods
MatchLabelKeysInPodTopologySpreadSelectorMerge
NominatedNodeNameForExpectation
PodCertificateRequest
PreventStaticPodAPIReferences
ProbeHostPodSecurityStandards
RelaxedServiceNameValidation
SchedulerAsyncAPICalls
SizeBasedListCostEstimate
StructuredAuthenticationConfigurationEgressSelector
TokenRequestServiceAccountUIDValidation
Feature gates removed in 1.34 compared to 1.33:
DevicePluginCDIDevices
ElasticIndexedJob
LegacySidecarContainers
PodDisruptionConditions
StatefulSetStartOrdinal
Feature gates locked to default true in 1.34 compared to 1.33:
AnonymousAuthConfigurableEndpoints
APIServerTracing
AuthorizeNodeWithSelectors
AuthorizeWithSelectors
ConsistentListFromCache
JobPodReplacementPolicy
KubeletCgroupDriverFromCRI
KubeletTracing
MultiCIDRServiceAllocator
NodeSwap
OrderedNamespaceDeletion
PodLifecycleSleepAction
PodLifecycleSleepActionAllowZero
ProbeHostPodSecurityStandards
RecoverVolumeExpansionFailure
RelaxedDNSSearchValidation
RelaxedEnvironmentVariableValidation
ResilientWatchCacheInitialization
SchedulerQueueingHints
SeparateTaintEvictionController
StreamingCollectionEncodingToJSON
StreamingCollectionEncodingToProtobuf
StructuredAuthenticationConfiguration
WinDSR
WinOverlay
Feature gates locked to default false in 1.34 compared to 1.33:
* feat: Maintain kube-apiserver admission plugins for 1.34
./hack/compare-k8s-admission-plugins.sh 1.33 1.34
Admission plugins added in 1.34 compared to 1.33:
Admission plugins removed in 1.34 compared to 1.33:
* feat: Maintain apigroups for 1.34
./hack/compare-k8s-api-groups.sh 1.33 1.34
Kubernetes API group versions added in 1.34 compared to 1.33:
resource.k8s.io/v1
Kubernetes API GVRs added in 1.34 compared to 1.33:
admissionregistration.k8s.io/v1beta1/mutatingadmissionpolicies
admissionregistration.k8s.io/v1beta1/mutatingadmissionpolicybindings
certificates.k8s.io/v1alpha1/podcertificaterequests
resource.k8s.io/v1/deviceclasses
resource.k8s.io/v1/resourceclaims
resource.k8s.io/v1/resourceclaimtemplates
resource.k8s.io/v1/resourceslices
storage.k8s.io/v1/volumeattributesclasses
Kubernetes API group versions removed in 1.34 compared to 1.33:
networking.k8s.io/v1alpha1
Kubernetes API GVRs removed in 1.34 compared to 1.33:
networking.k8s.io/v1alpha1/ipaddresses
networking.k8s.io/v1alpha1/servicecidrs
resource.k8s.io/v1alpha3/deviceclasses
resource.k8s.io/v1alpha3/resourceclaims
resource.k8s.io/v1alpha3/resourceclaimtemplates
resource.k8s.io/v1alpha3/resourceslices
* feat: Maintain kubernetes-controller-manager controller mappings
kube-controller-manager controllers added in 1.34 compared to 1.33:
Added Controllers for API Group [certificates/v1alpha1]: podcertificaterequest-cleaner-controller
Added Controllers for API Group [resource/v1]: device-taint-eviction-controller resourceclaim-controller
Added Controllers for API Group [storage/v1]: volumeattributesclass-protection-controller
kube-controller-manager controllers removed in 1.34 compared to 1.33:
Removed Controllers for API Group [resource/v1beta1]: device-taint-eviction-controller resourceclaim-controller
Removed Controllers for API Group [storage/v1beta1]: volumeattributesclass-protection-controller
* feat: Maintain unneeded controllers for workerless Shoots for Kubernetes 1.34
* chore: Update DaemonSet controller comments
* chore: Add Kubernetes v1.34.0 to provider-local cloud profile
* chore: Bump kindest/node version to 1.34.0
* chore: Change example Shoot to refer CredentialsBinding
* Set `trafficDistribution` to `PreferSameZone` for kubernetes versions `>= 1.34`
* Adapt charts to new `trafficDistribution` value
* Adapt tests to new `trafficDistribution` value
* Update TopologyAwareRouting documentation
* Address linting findings
* Use `PreferClose` for ETCD's clientService trafficDistribution
* --- SEPARATOR ---
* Align `node-problem-detector` images
Co-authored-by: Ismail Alidzhikov <9372594+ialidzhikov@users.noreply.github.com>
* Adapt to new labels for metrics
https://github.com/kubernetes/kubernetes/pull/130161
* Enable `discovery.k8s.io/v1` API for workerless `Shoot`s
Without it, the `kube-apiserver` does not start, because the `EndpointSlice` informers do not sync.
* Fix wording / typo
Co-authored-by: Marc Vornetran
---------
Co-authored-by: Ismail Alidzhikov <9372594+ialidzhikov@users.noreply.github.com>
Co-authored-by: Marc Vornetran
---
README.md | 14 +-
.../charts/runtime/templates/service.yaml | 5 +-
.../admission-controller/service.yaml | 5 +-
.../runtime/templates/apiserver/service.yaml | 5 +-
.../components/cloudprofile/cloudprofile.yaml | 1 +
docs/development/new-kubernetes-version.md | 2 +-
docs/operations/topology_aware_routing.md | 18 +-
example/provider-local/shoot.yaml | 2 +-
hack/compute-k8s-controllers.sh | 1 +
imagevector/containers.yaml | 19 +
.../v1alpha1/validation/garden_test.go | 5 +-
pkg/component/autoscaling/vpa/vpa_test.go | 23 +
pkg/component/etcd/etcd/etcd.go | 6 +
pkg/component/etcd/etcd/etcd_test.go | 4 +-
.../admission_controller_test.go | 4 +-
.../gardener/apiserver/apiserver_test.go | 35 +-
.../dashboard/terminal/terminal_test.go | 13 +
.../kubernetes/apiserver/deployment.go | 6 +-
.../apiserverexposure/service_test.go | 15 +
.../controllermanager/controllermanager.go | 4 +
.../controllermanager_test.go | 4 +
.../templates/service-internal.yaml | 5 +-
.../garden-shoot/apiserver-overview.json | 6 +-
.../apiserver-storage-details.json | 2 +-
pkg/provider-local/node/Dockerfile | 2 +-
.../helper/daemon_controller.go | 14 +-
pkg/utils/gardener/topology_aware_routing.go | 7 +-
.../gardener/topology_aware_routing_test.go | 21 +
pkg/utils/kubernetes/controllers.go | 14 +-
pkg/utils/validation/apigroups/apigroups.go | 23 +-
pkg/utils/validation/features/featuregates.go | 511 +++++++++---------
.../validation/kubernetesversion/version.go | 1 +
.../kubernetesversion/version_test.go | 3 +-
33 files changed, 505 insertions(+), 295 deletions(-)
diff --git a/README.md b/README.md
index fbfe9ecf56f..64d06e2ff6c 100644
--- a/README.md
+++ b/README.md
@@ -41,13 +41,13 @@ Currently, Gardener is certified for K8s versions up to v1.33, see [the conforma
Continuous conformance test results of the latest stable Gardener release are uploaded regularly to the CNCF test grid:
-| Provider/K8s | v1.33 | v1.32 | v1.31 | v1.30 | v1.29 |
-| ------------ |-----|-----| ------------ | ------------ | ------------ |
-| **AWS** | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20AWS) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20AWS) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20AWS) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20AWS) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20AWS) |
-| **Azure** | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20Azure) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20Azure) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20Azure) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20Azure) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20Azure) |
-| **GCP** | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20GCE) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20GCE) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20GCE) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20GCE) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20GCE) |
-| **OpenStack** | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20OpenStack) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20OpenStack) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20OpenStack) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20OpenStack) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20OpenStack) |
-| **Alicloud** | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20Alibaba%20Cloud) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20Alibaba%20Cloud) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20Alibaba%20Cloud) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20Alibaba%20Cloud) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20Alibaba%20Cloud) |
+| Provider/K8s | v1.34 | v1.33 | v1.32 | v1.31 | v1.30 | v1.29 |
+|---------------|-------|-----|-----| ------------ | ------------ | ------------ |
+| **AWS** | N/A | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20AWS) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20AWS) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20AWS) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20AWS) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20AWS) |
+| **Azure** | N/A | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20Azure) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20Azure) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20Azure) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20Azure) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20Azure) |
+| **GCP** | N/A | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20GCE) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20GCE) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20GCE) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20GCE) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20GCE) |
+| **OpenStack** | N/A | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20OpenStack) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20OpenStack) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20OpenStack) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20OpenStack) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20OpenStack) |
+| **Alicloud** | N/A | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.33%20Alibaba%20Cloud) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.32%20Alibaba%20Cloud) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.31%20Alibaba%20Cloud) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.30%20Alibaba%20Cloud) | [](https://testgrid.k8s.io/conformance-gardener#Gardener,%20v1.29%20Alibaba%20Cloud) |
Get an overview of the test results at [testgrid](https://testgrid.k8s.io/conformance-gardener).
diff --git a/charts/gardener/admission-local/charts/runtime/templates/service.yaml b/charts/gardener/admission-local/charts/runtime/templates/service.yaml
index bf2c94637fd..a7c0846bb3d 100644
--- a/charts/gardener/admission-local/charts/runtime/templates/service.yaml
+++ b/charts/gardener/admission-local/charts/runtime/templates/service.yaml
@@ -22,6 +22,9 @@ spec:
- port: 443
protocol: TCP
targetPort: {{ .Values.webhookConfig.serverPort }}
- {{- if and .Values.service.topologyAwareRouting.enabled (semverCompare ">= 1.31-0" .Capabilities.KubeVersion.Version) }}
+ {{- if and .Values.service.topologyAwareRouting.enabled (semverCompare ">= 1.31-0" .Capabilities.KubeVersion.Version) (semverCompare "< 1.34-0" .Capabilities.KubeVersion.Version) }}
trafficDistribution: PreferClose
{{- end }}
+ {{- if and .Values.service.topologyAwareRouting.enabled (semverCompare ">= 1.34-0" .Capabilities.KubeVersion.Version) }}
+ trafficDistribution: PreferSameZone
+ {{- end }}
diff --git a/charts/gardener/controlplane/charts/runtime/templates/admission-controller/service.yaml b/charts/gardener/controlplane/charts/runtime/templates/admission-controller/service.yaml
index 85f1089dd16..1f243fbc6ca 100644
--- a/charts/gardener/controlplane/charts/runtime/templates/admission-controller/service.yaml
+++ b/charts/gardener/controlplane/charts/runtime/templates/admission-controller/service.yaml
@@ -37,7 +37,10 @@ spec:
protocol: TCP
port: {{ required ".Values.global.admission.config.server.metrics.port is required" .Values.global.admission.config.server.metrics.port }}
targetPort: {{ required ".Values.global.admission.config.server.metrics.port is required" .Values.global.admission.config.server.metrics.port }}
- {{- if and .Values.global.admission.service.topologyAwareRouting.enabled (semverCompare ">= 1.31-0" .Capabilities.KubeVersion.Version) }}
+ {{- if and .Values.global.admission.service.topologyAwareRouting.enabled (semverCompare ">= 1.31-0" .Capabilities.KubeVersion.Version) (semverCompare "< 1.34-0" .Capabilities.KubeVersion.Version) }}
trafficDistribution: PreferClose
{{- end }}
+ {{- if and .Values.global.admission.service.topologyAwareRouting.enabled (semverCompare ">= 1.34-0" .Capabilities.KubeVersion.Version) }}
+ trafficDistribution: PreferSameZone
+ {{- end }}
{{- end }}
diff --git a/charts/gardener/controlplane/charts/runtime/templates/apiserver/service.yaml b/charts/gardener/controlplane/charts/runtime/templates/apiserver/service.yaml
index 4a07022b61c..235c0d14ab9 100644
--- a/charts/gardener/controlplane/charts/runtime/templates/apiserver/service.yaml
+++ b/charts/gardener/controlplane/charts/runtime/templates/apiserver/service.yaml
@@ -30,7 +30,10 @@ spec:
- port: 443
protocol: TCP
targetPort: {{ .Values.global.apiserver.securePort | default 8443 }}
- {{- if and .Values.global.apiserver.service.topologyAwareRouting.enabled (semverCompare ">= 1.31-0" .Capabilities.KubeVersion.Version) }}
+ {{- if and .Values.global.admission.service.topologyAwareRouting.enabled (semverCompare ">= 1.31-0" .Capabilities.KubeVersion.Version) (semverCompare "< 1.34-0" .Capabilities.KubeVersion.Version) }}
trafficDistribution: PreferClose
{{- end }}
+ {{- if and .Values.global.admission.service.topologyAwareRouting.enabled (semverCompare ">= 1.34-0" .Capabilities.KubeVersion.Version) }}
+ trafficDistribution: PreferSameZone
+ {{- end }}
{{- end }}
diff --git a/dev-setup/gardenconfig/components/cloudprofile/cloudprofile.yaml b/dev-setup/gardenconfig/components/cloudprofile/cloudprofile.yaml
index 72aa13a25b0..c4d63fc10a7 100644
--- a/dev-setup/gardenconfig/components/cloudprofile/cloudprofile.yaml
+++ b/dev-setup/gardenconfig/components/cloudprofile/cloudprofile.yaml
@@ -8,6 +8,7 @@ spec:
- name: local
kubernetes:
versions:
+ - version: 1.34.0
- version: 1.33.0
- version: 1.32.0
- version: 1.31.1
diff --git a/docs/development/new-kubernetes-version.md b/docs/development/new-kubernetes-version.md
index 17ad2121a56..57759ce3fa3 100644
--- a/docs/development/new-kubernetes-version.md
+++ b/docs/development/new-kubernetes-version.md
@@ -104,7 +104,7 @@ There is a CI/CD job that runs periodically and releases a new `hyperkube` image
- The list of supported versions is meanwhile maintained [here](../../pkg/utils/validation/kubernetesversion/version.go) in the `SupportedVersions` variable.
- Maintain the Kubernetes feature gates used for validation of `Shoot` resources:
- The feature gates are maintained in [this](../../pkg/utils/validation/features/featuregates.go) file.
- - To maintain this list for new Kubernetes versions, run `hack/compare-k8s-feature-gates.sh ` (e.g. `hack/compare-k8s-feature-gates.sh v1.33 v1.34`).
+ - To maintain this list for new Kubernetes versions, run `hack/compare-k8s-feature-gates.sh ` (e.g. `hack/compare-k8s-feature-gates.sh 1.34 1.35`).
- It will present 3 lists of feature gates: those added and those removed in `` compared to `` and feature gates that got locked to default in ``.
- Add all added feature gates to the map with `` as `AddedInVersion` and no `RemovedInVersion`.
- For any removed feature gates, add `` as `RemovedInVersion` to the already existing feature gate in the map.
diff --git a/docs/operations/topology_aware_routing.md b/docs/operations/topology_aware_routing.md
index 380d9c00c98..599b878a1e7 100644
--- a/docs/operations/topology_aware_routing.md
+++ b/docs/operations/topology_aware_routing.md
@@ -44,7 +44,7 @@ We reported the drawbacks related to the `TopologyAwareHints` feature in [kubern
The `ServiceTrafficDistribution` allows expressing preferences for how traffic should be routed to Service endpoints. For more details, see [upstream documentation](https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-distribution) of the feature.
-The `PreferClose` strategy allows traffic to be routed to Service endpoints in topology-aware and predictable manner.
+The `PreferSameZone` strategy allows traffic to be routed to Service endpoints in topology-aware and predictable manner.
It is simpler than `service.kubernetes.io/topology-mode: auto` - if there are Service endpoints which reside in the same zone as the client, traffic is routed to one of the endpoints within the same zone as the client. If the client's zone does not have any available Service endpoints, traffic is routed to any available endpoint within the cluster.
## How to make a Service topology-aware
@@ -82,9 +82,9 @@ spec:
trafficDistribution: PreferClose
```
-### How to make a Service topology-aware in Kubernetes >= 1.32
+### How to make a Service topology-aware in Kubernetes 1.32 to 1.33
-In Kubernetes >= 1.32, `ServiceTrafficDistribution` is being used to make a Service topology-aware. The `.spec.trafficDistribution` field has to be set to `PreferClose`:
+In Kubernetes 1.32 to 1.33, `ServiceTrafficDistribution` is being used to make a Service topology-aware. The `.spec.trafficDistribution` field has to be set to `PreferClose`:
```yaml
apiVersion: v1
@@ -93,6 +93,18 @@ spec:
trafficDistribution: PreferClose
```
+### How to make a Service topology-aware in Kubernetes 1.34 and later
+
+The value `PreferClose` has been deprecated in favor of `PreferSameZone` and `PreferSameNode`. `PreferSameZone` is an alias for the existing `PreferClose` to clarify its semantics. For more information, read the details in the [Kubernetes deprecation announcement](https://kubernetes.io/blog/2025/08/27/kubernetes-v1-34-release/#preferclose-traffic-distribution-is-deprecated).
+In Kubernetes 1.34 and later, `ServiceTrafficDistribution` is still used to make a Service topology-aware. The `.spec.trafficDistribution` field should be set to `PreferSameZone`:
+
+```yaml
+apiVersion: v1
+kind: Service
+spec:
+ trafficDistribution: PreferSameZone
+```
+
## Prerequisites for making a Service topology-aware
1. The Pods backing the Service should be spread on most of the available zones. This constraint should be ensured with appropriate scheduling constraints (topology spread constraints, (anti-)affinity). Enabling the feature for a Service with a single backing Pod or Pods all located in the same zone does not lead to a benefit.
diff --git a/example/provider-local/shoot.yaml b/example/provider-local/shoot.yaml
index 1b44b52eeb7..2b00920dfda 100644
--- a/example/provider-local/shoot.yaml
+++ b/example/provider-local/shoot.yaml
@@ -9,7 +9,7 @@ metadata:
spec:
cloudProfile:
name: local
- secretBindingName: local # dummy, doesn't contain any credentials
+ credentialsBindingName: local # dummy, doesn't contain any credentials
region: local
networking:
type: calico
diff --git a/hack/compute-k8s-controllers.sh b/hack/compute-k8s-controllers.sh
index abd7dd9fc73..1d0c9c4bb2c 100755
--- a/hack/compute-k8s-controllers.sh
+++ b/hack/compute-k8s-controllers.sh
@@ -57,6 +57,7 @@ declare -A path_map=(
["persistentvolume-binder-controller"]="pkg/controller/volume/persistentvolume/pv_controller_base.go"
["persistentvolume-expander-controller"]="pkg/controller/volume/expand/expand_controller.go"
["pod-garbage-collector-controller"]="pkg/controller/podgc/gc_controller.go"
+ ["podcertificaterequest-cleaner-controller"]="pkg/controller/certificates/cleaner/pcrcleaner.go"
["persistentvolume-protection-controller"]="pkg/controller/volume/pvprotection/pv_protection_controller.go"
["persistentvolumeclaim-protection-controller"]="pkg/controller/volume/pvcprotection/pvc_protection_controller.go"
["replicaset-controller"]="pkg/controller/replicaset/replica_set.go"
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index 3690190f464..2de27c9cfdd 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -496,10 +496,29 @@ images:
value:
- type: 'githubTeam'
teamname: 'gardener/gardener-core-networking-maintainers'
+ - name: node-problem-detector
+ sourceRepository: github.com/kubernetes/node-problem-detector
+ repository: registry.k8s.io/node-problem-detector/node-problem-detector
+ tag: "v1.34.0"
+ targetVersion: ">= 1.34"
+ labels:
+ - name: 'gardener.cloud/cve-categorisation'
+ value:
+ network_exposure: 'private'
+ authentication_enforced: false
+ user_interaction: 'end-user'
+ confidentiality_requirement: 'low'
+ integrity_requirement: 'high'
+ availability_requirement: 'low'
+ - name: 'cloud.gardener.cnudie/responsibles'
+ value:
+ - type: 'githubTeam'
+ teamname: 'gardener/mcm-maintainers'
- name: node-problem-detector
sourceRepository: github.com/kubernetes/node-problem-detector
repository: registry.k8s.io/node-problem-detector/node-problem-detector
tag: "v0.8.22"
+ targetVersion: "< 1.34"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
diff --git a/pkg/apis/operator/v1alpha1/validation/garden_test.go b/pkg/apis/operator/v1alpha1/validation/garden_test.go
index 8317fa91a4d..db8961eda02 100644
--- a/pkg/apis/operator/v1alpha1/validation/garden_test.go
+++ b/pkg/apis/operator/v1alpha1/validation/garden_test.go
@@ -810,10 +810,7 @@ var _ = Describe("Validation Tests", func() {
},
}
- Expect(ValidateGarden(garden, extensions)).To(ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeNotSupported),
- "Field": Equal("spec.virtualCluster.kubernetes.version"),
- }))))
+ Expect(ValidateGarden(garden, extensions)).To(BeEmpty())
})
It("should forbid setting rotate-etcd-encryption-key-start annotation when k8s version is >= v1.34", func() {
diff --git a/pkg/component/autoscaling/vpa/vpa_test.go b/pkg/component/autoscaling/vpa/vpa_test.go
index 96cb5ff06f7..8b78011ccf1 100644
--- a/pkg/component/autoscaling/vpa/vpa_test.go
+++ b/pkg/component/autoscaling/vpa/vpa_test.go
@@ -2255,6 +2255,29 @@ var _ = Describe("VPA", func() {
valuesAdmissionController.TopologyAwareRoutingEnabled = true
})
+ When("runtime Kubernetes version is >= 1.34", func() {
+ BeforeEach(func() {
+ runtimeKubernetesVersion = semver.MustParse("1.34.0")
+ })
+
+ It("should successfully deploy with expected vpa-webhook service annotation, label and spec field", func() {
+ vpa = New(c, namespace, sm, Values{
+ ClusterType: component.ClusterTypeShoot,
+ SecretNameServerCA: secretNameCA,
+ RuntimeKubernetesVersion: runtimeKubernetesVersion,
+ AdmissionController: valuesAdmissionController,
+ Recommender: valuesRecommender,
+ Updater: valuesUpdater,
+ })
+ Expect(vpa.Deploy(ctx)).To(Succeed())
+
+ actual := &corev1.Service{}
+ Expect(c.Get(ctx, client.ObjectKey{Namespace: namespace, Name: "vpa-webhook"}, actual)).To(Succeed())
+
+ Expect(actual.Spec.TrafficDistribution).To(PointTo(Equal(corev1.ServiceTrafficDistributionPreferSameZone)))
+ })
+ })
+
When("runtime Kubernetes version is >= 1.32", func() {
BeforeEach(func() {
runtimeKubernetesVersion = semver.MustParse("1.32.1")
diff --git a/pkg/component/etcd/etcd/etcd.go b/pkg/component/etcd/etcd/etcd.go
index 9a4140a6b11..301fc83fae9 100644
--- a/pkg/component/etcd/etcd/etcd.go
+++ b/pkg/component/etcd/etcd/etcd.go
@@ -50,6 +50,7 @@ import (
"github.com/gardener/gardener/pkg/utils/kubernetes/health"
secretsutils "github.com/gardener/gardener/pkg/utils/secrets"
secretsmanager "github.com/gardener/gardener/pkg/utils/secrets/manager"
+ versionutils "github.com/gardener/gardener/pkg/utils/version"
)
// Class is a string type alias for etcd classes.
@@ -260,6 +261,11 @@ func (e *etcd) Deploy(ctx context.Context) error {
clientService := &corev1.Service{}
gardenerutils.ReconcileTopologyAwareRoutingSettings(clientService, e.values.TopologyAwareRoutingEnabled, e.values.RuntimeKubernetesVersion)
+ // TODO(tobschli): Remove this once once etcd druid allows PreferSameZone.
+ if e.values.TopologyAwareRoutingEnabled && versionutils.ConstraintK8sGreaterEqual134.Check(e.values.RuntimeKubernetesVersion) {
+ clientService.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferClose)
+ }
+
ports := []networkingv1.NetworkPolicyPort{
{Port: ptr.To(intstr.FromInt32(etcdconstants.PortEtcdClient)), Protocol: ptr.To(corev1.ProtocolTCP)},
{Port: ptr.To(intstr.FromInt32(etcdconstants.PortBackupRestore)), Protocol: ptr.To(corev1.ProtocolTCP)},
diff --git a/pkg/component/etcd/etcd/etcd_test.go b/pkg/component/etcd/etcd/etcd_test.go
index b8b064d7503..2944a4be7a8 100644
--- a/pkg/component/etcd/etcd/etcd_test.go
+++ b/pkg/component/etcd/etcd/etcd_test.go
@@ -186,7 +186,9 @@ var _ = Describe("Etcd", func() {
},
}
if topologyAwareRoutingEnabled {
- if versionutils.ConstraintK8sGreaterEqual132.Check(runtimeKubernetesVersion) {
+ if versionutils.ConstraintK8sGreaterEqual134.Check(runtimeKubernetesVersion) {
+ clientService.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferSameZone)
+ } else if versionutils.ConstraintK8sGreaterEqual132.Check(runtimeKubernetesVersion) {
clientService.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferClose)
} else if versionutils.ConstraintK8sEqual131.Check(runtimeKubernetesVersion) {
clientService.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferClose)
diff --git a/pkg/component/gardener/admissioncontroller/admission_controller_test.go b/pkg/component/gardener/admissioncontroller/admission_controller_test.go
index 8852a129a9a..6d7fe49904c 100644
--- a/pkg/component/gardener/admissioncontroller/admission_controller_test.go
+++ b/pkg/component/gardener/admissioncontroller/admission_controller_test.go
@@ -760,7 +760,9 @@ func service(namespace string, testValues Values) *corev1.Service {
}
if testValues.TopologyAwareRoutingEnabled {
- if versionutils.ConstraintK8sGreaterEqual132.Check(testValues.RuntimeVersion) {
+ if versionutils.ConstraintK8sGreaterEqual134.Check(testValues.RuntimeVersion) {
+ svc.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferSameZone)
+ } else if versionutils.ConstraintK8sGreaterEqual132.Check(testValues.RuntimeVersion) {
svc.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferClose)
} else if versionutils.ConstraintK8sEqual131.Check(testValues.RuntimeVersion) {
svc.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferClose)
diff --git a/pkg/component/gardener/apiserver/apiserver_test.go b/pkg/component/gardener/apiserver/apiserver_test.go
index 744b8632ca6..36a799c1a9d 100644
--- a/pkg/component/gardener/apiserver/apiserver_test.go
+++ b/pkg/component/gardener/apiserver/apiserver_test.go
@@ -207,7 +207,6 @@ var _ = Describe("GardenerAPIServer", func() {
Labels: map[string]string{
"app": "gardener",
"role": "apiserver",
- "endpoint-slice-hints.resources.gardener.cloud/consider": "true",
},
},
Spec: corev1.ServiceSpec{
@@ -221,7 +220,7 @@ var _ = Describe("GardenerAPIServer", func() {
Protocol: corev1.ProtocolTCP,
TargetPort: intstr.FromInt32(8443),
}},
- TrafficDistribution: ptr.To(corev1.ServiceTrafficDistributionPreferClose),
+ TrafficDistribution: ptr.To(corev1.ServiceTrafficDistributionPreferSameZone),
},
}
@@ -1366,6 +1365,23 @@ kubeConfigFile: /etc/kubernetes/admission-kubeconfigs/validatingadmissionwebhook
Expect(managedResourceSecretVirtual.Labels["resources.gardener.cloud/garbage-collectable-reference"]).To(Equal("true"))
})
+ Context("Kubernetes version >= 1.34", func() {
+ BeforeEach(func() {
+ values.RuntimeVersion = semver.MustParse("1.34.0")
+ deployer = New(fakeClient, namespace, fakeSecretManager, values)
+ })
+
+ It("should successfully deploy all resources", func() {
+ expectedRuntimeObjects = append(
+ expectedRuntimeObjects,
+ podDisruptionBudget,
+ serviceRuntime,
+ )
+
+ Expect(managedResourceRuntime).To(consistOf(expectedRuntimeObjects...))
+ })
+ })
+
Context("Kubernetes version >= 1.31", func() {
BeforeEach(func() {
values.RuntimeVersion = semver.MustParse("1.31.0")
@@ -1373,6 +1389,9 @@ kubeConfigFile: /etc/kubernetes/admission-kubeconfigs/validatingadmissionwebhook
})
It("should successfully deploy all resources", func() {
+ serviceRuntime.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferClose)
+ metav1.SetMetaDataLabel(&serviceRuntime.ObjectMeta, "endpoint-slice-hints.resources.gardener.cloud/consider", "true")
+
expectedRuntimeObjects = append(
expectedRuntimeObjects,
podDisruptionBudget,
@@ -1381,6 +1400,11 @@ kubeConfigFile: /etc/kubernetes/admission-kubeconfigs/validatingadmissionwebhook
Expect(managedResourceRuntime).To(consistOf(expectedRuntimeObjects...))
})
+
+ AfterEach(func() {
+ delete(serviceRuntime.Labels, "endpoint-slice-hints.resources.gardener.cloud/consider")
+ serviceRuntime.Spec.TrafficDistribution = nil
+ })
})
Context("Kubernetes version < 1.31", func() {
@@ -1391,6 +1415,7 @@ kubeConfigFile: /etc/kubernetes/admission-kubeconfigs/validatingadmissionwebhook
It("should successfully deploy all resources", func() {
metav1.SetMetaDataAnnotation(&serviceRuntime.ObjectMeta, "service.kubernetes.io/topology-mode", "auto")
+ metav1.SetMetaDataLabel(&serviceRuntime.ObjectMeta, "endpoint-slice-hints.resources.gardener.cloud/consider", "true")
serviceRuntime.Spec.TrafficDistribution = nil
expectedRuntimeObjects = append(
@@ -1401,6 +1426,12 @@ kubeConfigFile: /etc/kubernetes/admission-kubeconfigs/validatingadmissionwebhook
Expect(managedResourceRuntime).To(consistOf(expectedRuntimeObjects...))
})
+
+ AfterEach(func() {
+ delete(serviceRuntime.Annotations, "service.kubernetes.io/topology-mode")
+ delete(serviceRuntime.Labels, "endpoint-slice-hints.resources.gardener.cloud/consider")
+ serviceRuntime.Spec.TrafficDistribution = nil
+ })
})
})
})
diff --git a/pkg/component/gardener/dashboard/terminal/terminal_test.go b/pkg/component/gardener/dashboard/terminal/terminal_test.go
index dd9fd9bf7ea..03c577577ba 100644
--- a/pkg/component/gardener/dashboard/terminal/terminal_test.go
+++ b/pkg/component/gardener/dashboard/terminal/terminal_test.go
@@ -725,6 +725,19 @@ server:
topologyAwareRouting = true
})
+ When("runtime Kubernetes version is >= 1.34", func() {
+ BeforeEach(func() {
+ runtimeVersion = semver.MustParse("1.34.0")
+ })
+
+ It("should successfully deploy all resources", func() {
+ service.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferSameZone)
+
+ Expect(managedResourceRuntime).To(consistOf(expectedRuntimeObjects...))
+ Expect(managedResourceVirtual).To(consistOf(expectedVirtualObjects...))
+ })
+ })
+
When("runtime Kubernetes version is >= 1.32", func() {
BeforeEach(func() {
runtimeVersion = semver.MustParse("1.32.1")
diff --git a/pkg/component/kubernetes/apiserver/deployment.go b/pkg/component/kubernetes/apiserver/deployment.go
index d08493aec55..dc87ecac884 100644
--- a/pkg/component/kubernetes/apiserver/deployment.go
+++ b/pkg/component/kubernetes/apiserver/deployment.go
@@ -36,6 +36,7 @@ import (
netutils "github.com/gardener/gardener/pkg/utils/net"
"github.com/gardener/gardener/pkg/utils/secrets"
secretsmanager "github.com/gardener/gardener/pkg/utils/secrets/manager"
+ versionutils "github.com/gardener/gardener/pkg/utils/version"
)
const (
@@ -439,11 +440,14 @@ func (k *kubeAPIServer) computeKubeAPIServerArgs() []string {
"apps/v1": false,
"autoscaling/v2": false,
"batch/v1": false,
- "discovery.k8s.io/v1": false,
"policy/v1": false,
"storage.k8s.io/v1/csinodes": false,
}
+ if versionutils.ConstraintK8sLess134.Check(k.values.Version) {
+ disableAPIs["discovery.k8s.io/v1"] = false
+ }
+
// Allow users to explicitly enable disabled APIs via RuntimeConfig.
k.values.RuntimeConfig = utils.MergeStringMaps(disableAPIs, k.values.RuntimeConfig)
}
diff --git a/pkg/component/kubernetes/apiserverexposure/service_test.go b/pkg/component/kubernetes/apiserverexposure/service_test.go
index 2a1fdb1e8de..701fcb6a8ee 100644
--- a/pkg/component/kubernetes/apiserverexposure/service_test.go
+++ b/pkg/component/kubernetes/apiserverexposure/service_test.go
@@ -191,6 +191,21 @@ var _ = Describe("#Service", func() {
values.TopologyAwareRoutingEnabled = true
})
+ When("runtime Kubernetes version is >= 1.34", func() {
+ BeforeEach(func() {
+ values.RuntimeKubernetesVersion = semver.MustParse("1.34.0")
+ })
+
+ It("should successfully deploy with expected kube-apiserver service annotation, label and spec field", func() {
+ Expect(defaultDepWaiter.Deploy(ctx)).To(Succeed())
+
+ actual := &corev1.Service{}
+ Expect(c.Get(ctx, client.ObjectKey{Namespace: namespace, Name: expectedName}, actual)).To(Succeed())
+
+ Expect(actual.Spec.TrafficDistribution).To(PointTo(Equal(corev1.ServiceTrafficDistributionPreferSameZone)))
+ })
+ })
+
When("runtime Kubernetes version is >= 1.32", func() {
BeforeEach(func() {
values.RuntimeKubernetesVersion = semver.MustParse("1.32.1")
diff --git a/pkg/component/kubernetes/controllermanager/controllermanager.go b/pkg/component/kubernetes/controllermanager/controllermanager.go
index 5f3db5c1047..e0e32bf6663 100644
--- a/pkg/component/kubernetes/controllermanager/controllermanager.go
+++ b/pkg/component/kubernetes/controllermanager/controllermanager.go
@@ -726,6 +726,10 @@ func (k *kubeControllerManager) computeCommand(port int32) []string {
if versionutils.ConstraintK8sGreaterEqual133.Check(k.values.TargetVersion) {
controllersToDisable.Insert("device-taint-eviction-controller")
}
+
+ if versionutils.ConstraintK8sGreaterEqual134.Check(k.values.TargetVersion) {
+ controllersToDisable.Insert("podcertificaterequest-cleaner-controller")
+ }
}
command = append(command,
diff --git a/pkg/component/kubernetes/controllermanager/controllermanager_test.go b/pkg/component/kubernetes/controllermanager/controllermanager_test.go
index a0fac419b58..5fd8884da22 100644
--- a/pkg/component/kubernetes/controllermanager/controllermanager_test.go
+++ b/pkg/component/kubernetes/controllermanager/controllermanager_test.go
@@ -1054,6 +1054,10 @@ func commandForKubernetesVersion(
controllers = append(controllers, "-device-taint-eviction-controller")
}
+ if versionutils.ConstraintK8sGreaterEqual134.Check(version) {
+ controllers = append(controllers, "-podcertificaterequest-cleaner-controller")
+ }
+
controllers = append(controllers,
"-endpoint",
"-ephemeral-volume",
diff --git a/pkg/component/networking/istio/charts/istio/istio-ingress/templates/service-internal.yaml b/pkg/component/networking/istio/charts/istio/istio-ingress/templates/service-internal.yaml
index 4dee8012736..8375df4ce11 100644
--- a/pkg/component/networking/istio/charts/istio/istio-ingress/templates/service-internal.yaml
+++ b/pkg/component/networking/istio/charts/istio/istio-ingress/templates/service-internal.yaml
@@ -32,6 +32,9 @@ spec:
- IPv4
ipFamilyPolicy: PreferDualStack
{{- end }}
-{{- if semverCompare ">= 1.31-0" .Values.kubernetesVersion }}
+{{- if and (semverCompare ">= 1.31-0" .Values.kubernetesVersion) (semverCompare "< 1.34-0" .Values.kubernetesVersion) }}
trafficDistribution: PreferClose
{{- end }}
+{{- if semverCompare ">= 1.34-0" .Values.kubernetesVersion }}
+ trafficDistribution: PreferSameZone
+{{- end }}
diff --git a/pkg/component/observability/plutono/dashboards/garden-shoot/apiserver-overview.json b/pkg/component/observability/plutono/dashboards/garden-shoot/apiserver-overview.json
index 2e708a4807c..8308e8e7a51 100644
--- a/pkg/component/observability/plutono/dashboards/garden-shoot/apiserver-overview.json
+++ b/pkg/component/observability/plutono/dashboards/garden-shoot/apiserver-overview.json
@@ -2958,7 +2958,7 @@
"steppedLine": false,
"targets": [
{
- "expr": "histogram_quantile(0.90,sum(rate(apiserver_watch_events_sizes_bucket{job=~\"$job\",pod=~\"$pod\"}[$__rate_interval])) by(le,kind))",
+ "expr": "histogram_quantile(0.90,sum(rate(apiserver_watch_events_sizes_bucket{job=~\"$job\",pod=~\"$pod\"}[$__rate_interval])) by(le,resource))",
"interval": "",
"legendFormat": "{{kind}}",
"refId": "A"
@@ -3159,7 +3159,7 @@
"steppedLine": true,
"targets": [
{
- "expr": "sum(increase(watch_cache_capacity_increase_total{job=~\"$job\",pod=~\"$pod\"}[$__rate_interval])) by (resource)",
+ "expr": "sum(increase(watch_cache_capacity_increase_total{job=~\"$job\",pod=~\"$pod\"}[$__rate_interval])) by (group,resource)",
"interval": "",
"legendFormat": "{{resource}}",
"refId": "A"
@@ -3261,7 +3261,7 @@
"steppedLine": true,
"targets": [
{
- "expr": "sum(increase(watch_cache_capacity_decrease_total{job=~\"$job\",pod=~\"$pod\"}[$__rate_interval])) by (resource)",
+ "expr": "sum(increase(watch_cache_capacity_decrease_total{job=~\"$job\",pod=~\"$pod\"}[$__rate_interval])) by (group,resource)",
"interval": "",
"legendFormat": "{{resource}}",
"refId": "A"
diff --git a/pkg/component/observability/plutono/dashboards/garden-shoot/apiserver-storage-details.json b/pkg/component/observability/plutono/dashboards/garden-shoot/apiserver-storage-details.json
index 3bd2eb14e6e..faa696e5137 100644
--- a/pkg/component/observability/plutono/dashboards/garden-shoot/apiserver-storage-details.json
+++ b/pkg/component/observability/plutono/dashboards/garden-shoot/apiserver-storage-details.json
@@ -74,7 +74,7 @@
},
"targets": [
{
- "expr": "sum(rate(etcd_request_duration_seconds_bucket{job=~\"$apiserver\",type=~\"$type\",operation=~\"$operation\"}[$__rate_interval])) by (le)",
+ "expr": "sum(rate(etcd_request_duration_seconds_bucket{job=~\"$apiserver\",group=\"$group\",resource=\"$resource\",operation=~\"$operation\"}[$__rate_interval])) by (le)",
"format": "heatmap",
"interval": "",
"intervalFactor": 3,
diff --git a/pkg/provider-local/node/Dockerfile b/pkg/provider-local/node/Dockerfile
index 78c829576c4..a4d81b1611a 100644
--- a/pkg/provider-local/node/Dockerfile
+++ b/pkg/provider-local/node/Dockerfile
@@ -1,4 +1,4 @@
-FROM kindest/node:v1.33.4@sha256:25a6018e48dfcaee478f4a59af81157a437f15e6e140bf103f85a2e7cd0cbbf2
+FROM kindest/node:v1.34.0@sha256:7416a61b42b1662ca6ca89f02028ac133a309a2a30ba309614e8ec94d976dc5a
RUN apt-get update -yq && \
apt-get install -yq --no-install-recommends wget apparmor apparmor-utils jq openssh-server sudo logrotate
diff --git a/pkg/resourcemanager/controller/node/criticalcomponents/helper/daemon_controller.go b/pkg/resourcemanager/controller/node/criticalcomponents/helper/daemon_controller.go
index 0b95c433950..08db215e8aa 100644
--- a/pkg/resourcemanager/controller/node/criticalcomponents/helper/daemon_controller.go
+++ b/pkg/resourcemanager/controller/node/criticalcomponents/helper/daemon_controller.go
@@ -46,7 +46,8 @@ import (
// Returns true when a daemonset should continue running on a node if a daemonset pod is already
// running on that node.
//
-// Copied from https://github.com/kubernetes/kubernetes/blob/v1.33.0/pkg/controller/daemon/daemon_controller.go#L1299-L1330
+// Copied from https://github.com/kubernetes/kubernetes/blob/v1.34.0/pkg/controller/daemon/daemon_controller.go#L1275-L1306
+// First if block semantically equally changed due to golangci-lint finding QF1001.
func NodeShouldRunDaemonPod(node *corev1.Node, ds *appsv1.DaemonSet) (bool, bool) {
pod := NewPod(ds, node.Name)
@@ -73,7 +74,7 @@ func NodeShouldRunDaemonPod(node *corev1.Node, ds *appsv1.DaemonSet) (bool, bool
}
// predicates checks if a DaemonSet's pod can run on a node.
-// Copied from https://github.com/kubernetes/kubernetes/blob/v1.33.0/pkg/controller/daemon/daemon_controller.go#L1332-L1342
+// Copied from https://github.com/kubernetes/kubernetes/blob/v1.34.0/pkg/controller/daemon/daemon_controller.go#L1308-L1318
func predicates(pod *corev1.Pod, node *corev1.Node, taints []corev1.Taint) (fitsNodeName, fitsNodeAffinity, fitsTaints bool) {
fitsNodeName = len(pod.Spec.NodeName) == 0 || pod.Spec.NodeName == node.Name
// Ignore parsing errors for backwards compatibility.
@@ -86,7 +87,7 @@ func predicates(pod *corev1.Pod, node *corev1.Node, taints []corev1.Taint) (fits
}
// NewPod creates a new pod
-// Copied from https://github.com/kubernetes/kubernetes/blob/v1.33.0/pkg/controller/daemon/daemon_controller.go#L1344-L1354
+// Copied from https://github.com/kubernetes/kubernetes/blob/v1.34.0/pkg/controller/daemon/daemon_controller.go#L1320-L1330
func NewPod(ds *appsv1.DaemonSet, nodeName string) *corev1.Pod {
newPod := &corev1.Pod{Spec: ds.Spec.Template.Spec, ObjectMeta: ds.Spec.Template.ObjectMeta}
newPod.Namespace = ds.Namespace
@@ -99,7 +100,7 @@ func NewPod(ds *appsv1.DaemonSet, nodeName string) *corev1.Pod {
}
// AddOrUpdateDaemonPodTolerations apply necessary tolerations to DaemonSet Pods, e.g. node.kubernetes.io/not-ready:NoExecute.
-// Copied from https://github.com/kubernetes/kubernetes/blob/v1.33.0/pkg/controller/daemon/util/daemonset_util.go#L47-L102
+// Copied from https://github.com/kubernetes/kubernetes/blob/v1.34.0/pkg/controller/daemon/util/daemonset_util.go#L47-L102
func AddOrUpdateDaemonPodTolerations(spec *corev1.PodSpec) {
// DaemonSet pods shouldn't be deleted by NodeController in case of node problems.
// Add infinite toleration for taint notReady:NoExecute here
@@ -158,7 +159,7 @@ func AddOrUpdateDaemonPodTolerations(spec *corev1.PodSpec) {
// AddOrUpdateTolerationInPodSpec tries to add a toleration to the toleration list in PodSpec.
// Returns true if something was updated, false otherwise.
-// Copied from https://github.com/kubernetes/kubernetes/blob/v1.33.0/pkg/apis/core/v1/helper/helpers.go#L261-L287
+// Copied from https://github.com/kubernetes/kubernetes/blob/v1.34.0/pkg/apis/core/v1/helper/helpers.go#L261-L287
func AddOrUpdateTolerationInPodSpec(spec *corev1.PodSpec, toleration *corev1.Toleration) bool {
podTolerations := spec.Tolerations
@@ -187,7 +188,8 @@ func AddOrUpdateTolerationInPodSpec(spec *corev1.PodSpec, toleration *corev1.Tol
// Semantic can do semantic deep equality checks for core objects.
// Example: apiequality.Semantic.DeepEqual(aPod, aPodWithNonNilButEmptyMaps) == true
-// Copied from https://github.com/kubernetes/kubernetes/blob/v1.33.0/pkg/apis/core/helper/helpers.go#L92-L114
+// Copied from https://github.com/kubernetes/kubernetes/blob/v1.34.0/pkg/apis/core/helper/helpers.go#L92-L114
+// Changed time comparisons changed due to golangci-lint finding QF1009.
var Semantic = conversion.EqualitiesOrDie(
func(a, b resource.Quantity) bool {
// Ignore formatting, only care that numeric value stayed the same.
diff --git a/pkg/utils/gardener/topology_aware_routing.go b/pkg/utils/gardener/topology_aware_routing.go
index a0baa51c1d0..baa87391787 100644
--- a/pkg/utils/gardener/topology_aware_routing.go
+++ b/pkg/utils/gardener/topology_aware_routing.go
@@ -26,8 +26,11 @@ func ReconcileTopologyAwareRoutingSettings(service *corev1.Service, topologyAwar
if !topologyAwareRoutingEnabled {
return
}
-
- if versionutils.ConstraintK8sGreaterEqual132.Check(k8sVersion) {
+ if versionutils.ConstraintK8sGreaterEqual134.Check(k8sVersion) {
+ // For Kubernetes >= 1.34, only use the PreferSameZone strategy of the ServiceTrafficDistribution feature.
+ // PreferClose is deprecated. PreferSameZone is a new alias for PreferClose (https://kubernetes.io/blog/2025/08/27/kubernetes-v1-34-release/#preferclose-traffic-distribution-is-deprecated).
+ service.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferSameZone)
+ } else if versionutils.ConstraintK8sGreaterEqual132.Check(k8sVersion) {
// For Kubernetes >= 1.32, only use the PreferClose strategy of the ServiceTrafficDistribution feature.
service.Spec.TrafficDistribution = ptr.To(corev1.ServiceTrafficDistributionPreferClose)
} else if versionutils.ConstraintK8sEqual131.Check(k8sVersion) {
diff --git a/pkg/utils/gardener/topology_aware_routing_test.go b/pkg/utils/gardener/topology_aware_routing_test.go
index b146f3e19a7..a0a7f3a2e58 100644
--- a/pkg/utils/gardener/topology_aware_routing_test.go
+++ b/pkg/utils/gardener/topology_aware_routing_test.go
@@ -17,6 +17,27 @@ import (
var _ = Describe("TopologyAwareRouting", func() {
Describe("#ReconcileTopologyAwareRoutingSettings", func() {
+ When("K8s version >= 1.34", func() {
+ It("should set traffic distribution field when topology-aware routing is enabled", func() {
+ service := &corev1.Service{
+ ObjectMeta: metav1.ObjectMeta{
+ Annotations: map[string]string{
+ "service.kubernetes.io/topology-aware-hints": "auto",
+ "service.kubernetes.io/topology-mode": "auto",
+ },
+ Labels: map[string]string{"endpoint-slice-hints.resources.gardener.cloud/consider": "true"},
+ },
+ }
+
+ ReconcileTopologyAwareRoutingSettings(service, true, semver.MustParse("1.34.0"))
+
+ Expect(service.Annotations).NotTo(HaveKey("service.kubernetes.io/topology-mode"))
+ Expect(service.Annotations).NotTo(HaveKey("service.kubernetes.io/topology-aware-hints"))
+ Expect(service.Labels).NotTo(HaveKey("endpoint-slice-hints.resources.gardener.cloud/consider"))
+ Expect(service.Spec.TrafficDistribution).To(PointTo(Equal(corev1.ServiceTrafficDistributionPreferSameZone)))
+ })
+ })
+
When("K8s version >= 1.32", func() {
It("should set traffic distribution field when topology-aware routing is enabled", func() {
service := &corev1.Service{
diff --git a/pkg/utils/kubernetes/controllers.go b/pkg/utils/kubernetes/controllers.go
index be6dabe4553..fa0dc4ba10d 100644
--- a/pkg/utils/kubernetes/controllers.go
+++ b/pkg/utils/kubernetes/controllers.go
@@ -51,6 +51,7 @@ var APIGroupControllerMap = map[string]map[string]versionutils.VersionRange{
},
"certificates/v1alpha1": {
"kube-apiserver-serving-clustertrustbundle-publisher-controller": {AddedInVersion: "1.32"},
+ "podcertificaterequest-cleaner-controller": {AddedInVersion: "1.34"},
},
"certificates/v1beta1": {
"csrsigning": {},
@@ -82,6 +83,10 @@ var APIGroupControllerMap = map[string]map[string]versionutils.VersionRange{
"rbac/v1": {
"clusterrole-aggregation": {},
},
+ "resource/v1": {
+ "device-taint-eviction-controller": {AddedInVersion: "1.34"},
+ "resourceclaim-controller": {AddedInVersion: "1.34"},
+ },
"resource/v1alpha2": {
"resource-claim-controller": {RemovedInVersion: "1.31"},
},
@@ -89,14 +94,15 @@ var APIGroupControllerMap = map[string]map[string]versionutils.VersionRange{
"resource-claim-controller": {AddedInVersion: "1.31", RemovedInVersion: "1.32"},
},
"resource/v1beta1": {
- "resource-claim-controller": {AddedInVersion: "1.32"},
- "device-taint-eviction-controller": {AddedInVersion: "1.33"},
+ "device-taint-eviction-controller": {AddedInVersion: "1.33", RemovedInVersion: "1.34"},
+ "resource-claim-controller": {AddedInVersion: "1.32", RemovedInVersion: "1.34"},
},
"storage/v1": {
- "selinux-warning-controller": {AddedInVersion: "1.32"},
+ "selinux-warning-controller": {AddedInVersion: "1.32"},
+ "volumeattributesclass-protection-controller": {AddedInVersion: "1.34"},
},
"storage/v1beta1": {
- "volumeattributesclass-protection-controller": {AddedInVersion: "1.32"},
+ "volumeattributesclass-protection-controller": {AddedInVersion: "1.32", RemovedInVersion: "1.34"},
},
"storagemigration/v1alpha1": {
"storage-version-migrator-controller": {AddedInVersion: "1.30"},
diff --git a/pkg/utils/validation/apigroups/apigroups.go b/pkg/utils/validation/apigroups/apigroups.go
index c86c778f342..8488fc7d4ed 100644
--- a/pkg/utils/validation/apigroups/apigroups.go
+++ b/pkg/utils/validation/apigroups/apigroups.go
@@ -49,7 +49,7 @@ var (
"flowcontrol.apiserver.k8s.io/v1beta3": {},
"internal.apiserver.k8s.io/v1alpha1": {},
"networking.k8s.io/v1": {Required: true, RequiredForWorkerless: true},
- "networking.k8s.io/v1alpha1": {},
+ "networking.k8s.io/v1alpha1": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.34"}},
"networking.k8s.io/v1beta1": {},
"node.k8s.io/v1": {},
"node.k8s.io/v1alpha1": {},
@@ -59,6 +59,7 @@ var (
"rbac.authorization.k8s.io/v1": {Required: true, RequiredForWorkerless: true},
"rbac.authorization.k8s.io/v1alpha1": {},
"rbac.authorization.k8s.io/v1beta1": {},
+ "resource.k8s.io/v1": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
"resource.k8s.io/v1alpha2": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
"resource.k8s.io/v1alpha3": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
"resource.k8s.io/v1beta1": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
@@ -83,6 +84,8 @@ var (
"admissionregistration.k8s.io/v1alpha1/mutatingadmissionpolicybindings": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
"admissionregistration.k8s.io/v1alpha1/validatingadmissionpolicies": {},
"admissionregistration.k8s.io/v1alpha1/validatingadmissionpolicybindings": {},
+ "admissionregistration.k8s.io/v1beta1/mutatingadmissionpolicies": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "admissionregistration.k8s.io/v1beta1/mutatingadmissionpolicybindings": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
"admissionregistration.k8s.io/v1beta1/mutatingwebhookconfigurations": {},
"admissionregistration.k8s.io/v1beta1/validatingadmissionpolicies": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
"admissionregistration.k8s.io/v1beta1/validatingadmissionpolicybindings": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
@@ -109,6 +112,7 @@ var (
"batch/v1beta1/cronjobs": {},
"certificates.k8s.io/v1/certificatesigningrequests": {Required: true},
"certificates.k8s.io/v1alpha1/clustertrustbundles": {},
+ "certificates.k8s.io/v1alpha1/podcertificaterequests": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
"certificates.k8s.io/v1beta1/clustertrustbundles": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
"certificates.k8s.io/v1beta1/certificatesigningrequests": {},
"coordination.k8s.io/v1/leases": {Required: true},
@@ -139,8 +143,8 @@ var (
"networking.k8s.io/v1/ipaddresses": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
"networking.k8s.io/v1/networkpolicies": {},
"networking.k8s.io/v1/servicecidrs": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "networking.k8s.io/v1alpha1/ipaddresses": {},
- "networking.k8s.io/v1alpha1/servicecidrs": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "networking.k8s.io/v1alpha1/ipaddresses": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.34"}},
+ "networking.k8s.io/v1alpha1/servicecidrs": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29", RemovedInVersion: "1.34"}},
"networking.k8s.io/v1beta1/ingressclasses": {},
"networking.k8s.io/v1beta1/ingresses": {},
"networking.k8s.io/v1beta1/ipaddresses": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
@@ -162,6 +166,10 @@ var (
"rbac.authorization.k8s.io/v1beta1/clusterroles": {},
"rbac.authorization.k8s.io/v1beta1/rolebindings": {},
"rbac.authorization.k8s.io/v1beta1/roles": {},
+ "resource.k8s.io/v1/deviceclasses": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "resource.k8s.io/v1/resourceclaims": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "resource.k8s.io/v1/resourceclaimtemplates": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "resource.k8s.io/v1/resourceslices": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
"resource.k8s.io/v1alpha2/podschedulingcontexts": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
"resource.k8s.io/v1alpha2/resourceclaimparameters": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30", RemovedInVersion: "1.31"}},
"resource.k8s.io/v1alpha2/resourceclaims": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
@@ -169,12 +177,12 @@ var (
"resource.k8s.io/v1alpha2/resourceclasses": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
"resource.k8s.io/v1alpha2/resourceclassparameters": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30", RemovedInVersion: "1.31"}},
"resource.k8s.io/v1alpha2/resourceslices": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30", RemovedInVersion: "1.31"}},
- "resource.k8s.io/v1alpha3/deviceclasses": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "resource.k8s.io/v1alpha3/deviceclasses": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31", RemovedInVersion: "1.34"}},
"resource.k8s.io/v1alpha3/devicetaintrules": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
"resource.k8s.io/v1alpha3/podschedulingcontexts": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31", RemovedInVersion: "1.32"}},
- "resource.k8s.io/v1alpha3/resourceclaims": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "resource.k8s.io/v1alpha3/resourceclaimtemplates": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "resource.k8s.io/v1alpha3/resourceslices": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "resource.k8s.io/v1alpha3/resourceclaims": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31", RemovedInVersion: "1.34"}},
+ "resource.k8s.io/v1alpha3/resourceclaimtemplates": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31", RemovedInVersion: "1.34"}},
+ "resource.k8s.io/v1alpha3/resourceslices": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31", RemovedInVersion: "1.34"}},
"resource.k8s.io/v1beta1/deviceclasses": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
"resource.k8s.io/v1beta1/resourceclaims": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
"resource.k8s.io/v1beta1/resourceclaimtemplates": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
@@ -191,6 +199,7 @@ var (
"storage.k8s.io/v1/csistoragecapacities": {},
"storage.k8s.io/v1/storageclasses": {},
"storage.k8s.io/v1/volumeattachments": {},
+ "storage.k8s.io/v1/volumeattributesclasses": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
"storage.k8s.io/v1alpha1/csistoragecapacities": {},
"storage.k8s.io/v1alpha1/volumeattachments": {},
"storage.k8s.io/v1alpha1/volumeattributesclasses": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
diff --git a/pkg/utils/validation/features/featuregates.go b/pkg/utils/validation/features/featuregates.go
index 9238b7dee69..4a2ef75c1db 100644
--- a/pkg/utils/validation/features/featuregates.go
+++ b/pkg/utils/validation/features/featuregates.go
@@ -27,251 +27,272 @@ var featureGateVersionRanges = map[string]*FeatureGateVersionRange{
"AllAlpha": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.17"}},
"AllBeta": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.17"}},
- "AdmissionWebhookMatchConditions": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "AggregatedDiscoveryRemoveBetaType": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "AllowDNSOnlyNodeCSR": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "AllowInsecureKubeletCertificateSigningRequests": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "AllowOverwriteTerminationGracePeriodSeconds": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "AllowServiceLBStatusOnNonLB": {LockedValue: false, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "AllowUnsafeMalformedObjectDeletion": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "AllowParsingUserUIDFromCertAuth": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "APIListChunking": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "APIPriorityAndFairness": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "APIResponseCompression": {},
- "APISelfSubjectReview": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "APIServerIdentity": {},
- "APIServerTracing": {},
- "APIServingWithRoutine": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "AggregatedDiscoveryEndpoint": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "AnonymousAuthConfigurableEndpoints": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "AnyVolumeDataSource": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
- "AppArmor": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "AppArmorFields": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30", RemovedInVersion: "1.33"}},
- "AuthorizeNodeWithSelectors": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "AuthorizeWithSelectors": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "BtreeWatchCache": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "CBORServingAndStorage": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "CloudControllerManagerWebhook": {},
- "CloudDualStackNodeIPs": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.32"}},
- "ClusterTrustBundle": {},
- "ClusterTrustBundleProjection": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "ComponentFlagz": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "ComponentSLIs": {},
- "ComponentStatusz": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "ConcurrentWatchObjectDecode": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "ContainerCheckpoint": {},
- "ContainerStopSignals": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "ContextualLogging": {LockedValue: true, LockedToDefaultInVersion: "1.30"},
- "ConsistentHTTPGetHandlers": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.26", RemovedInVersion: "1.31"}},
- "ConsistentListFromCache": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "CoordinatedLeaderElection": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "CPUManager": {LockedValue: true, LockedToDefaultInVersion: "1.26", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "CPUManagerPolicyAlphaOptions": {},
- "CPUManagerPolicyBetaOptions": {},
- "CPUManagerPolicyOptions": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
- "CRDValidationRatcheting": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "CronJobsScheduledAnnotation": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "CrossNamespaceVolumeDataSource": {},
- "CSIMigrationAzureFile": {LockedValue: true, LockedToDefaultInVersion: "1.27", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "CSIMigrationPortworx": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
- "CSIMigrationRBD": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "CSINodeExpandSecret": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "CSIVolumeHealth": {},
- "CustomCPUCFSQuotaPeriod": {},
- "CustomResourceFieldSelectors": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "CustomResourceValidationExpressions": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "DeclarativeValidation": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "DeclarativeValidationTakeover": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "DefaultHostNetworkHostPortsInPodTemplates": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.31"}},
- "DeploymentReplicaSetTerminatingReplicas": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "DevicePluginCDIDevices": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "DisableAllocatorDualWrite": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "DisableCloudProviders": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "DisableCPUQuotaWithExclusiveCPUs": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "DisableKubeletCloudCredentialProviders": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "DisableNodeKubeProxyVersion": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "DRAAdminAccess": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "DRAControlPlaneController": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.26", RemovedInVersion: "1.32"}},
- "DRADeviceTaints": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "DRAPartitionableDevices": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "DRAPrioritizedList": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "DRAResourceClaimDeviceStatus": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "DynamicResourceAllocation": {},
- "EfficientWatchResumption": {LockedValue: true, LockedToDefaultInVersion: "1.24", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "ElasticIndexedJob": {LockedValue: true, LockedToDefaultInVersion: "1.31"},
- "EventedPLEG": {},
- "ExecProbeTimeout": {},
- "ExpandedDNSConfig": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "ExperimentalHostUserNamespaceDefaulting": {LockedValue: false, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "ExternalServiceAccountTokenSigner": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "GitRepoVolumeDriver": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "GracefulNodeShutdown": {},
- "GracefulNodeShutdownBasedOnPodPriority": {},
- "HonorPVReclaimPolicy": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
- "HPAConfigurableTolerance": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "HPAContainerMetrics": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.20", RemovedInVersion: "1.32"}},
- "HPAScaleToZero": {},
- "IPTablesOwnershipCleanup": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "ImageMaximumGCAge": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "ImageVolume": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "InPlacePodVerticalScaling": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.27"}},
- "InPlacePodVerticalScalingAllocatedStatus": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "InPlacePodVerticalScalingExclusiveCPUs": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "InTreePluginAWSUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "InTreePluginAzureDiskUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "InTreePluginAzureFileUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "InTreePluginGCEUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "InTreePluginOpenStackUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "InTreePluginPortworxUnregister": {},
- "InTreePluginRBDUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "InTreePluginvSphereUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "InformerResourceVersion": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "JobBackoffLimitPerIndex": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "JobManagedBy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "JobPodFailurePolicy": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "JobPodReplacementPolicy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "JobReadyPods": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "JobSuccessPolicy": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "KMSv1": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "KMSv2": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{AddedInVersion: "1.25", RemovedInVersion: "1.32"}},
- "KMSv2KDF": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.32"}},
- "KubeletEnsureSecretPulledImages": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "KubeletCgroupDriverFromCRI": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "KubeletCrashLoopBackOffMax": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "KubeletFineGrainedAuthz": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "KubeletInUserNamespace": {},
- "KubeletPodResources": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "KubeletPodResourcesDynamicResources": {},
- "KubeletPodResourcesGet": {},
- "KubeletPodResourcesGetAllocatable": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "KubeletPSI": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "KubeletRegistrationGetOnExistsOnly": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "KubeletSeparateDiskGC": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "KubeletServiceAccountTokenForCredentialProviders": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "KubeletTracing": {},
- "KubeProxyDrainingTerminatingNodes": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.33"}},
- "LegacyServiceAccountTokenCleanUp": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.32"}},
- "LegacyServiceAccountTokenTracking": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{AddedInVersion: "1.26", RemovedInVersion: "1.30"}},
- "LegacySidecarContainers": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "LoadBalancerIPMode": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "ListFromCacheSnapshot": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "LocalStorageCapacityIsolationFSQuotaMonitoring": {},
- "LogarithmicScaleDown": {LockedValue: true, LockedToDefaultInVersion: "1.31"},
- "MatchLabelKeysInPodAffinity": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "MatchLabelKeysInPodTopologySpread": {},
- "MaxUnavailableStatefulSet": {},
- "MemoryManager": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.21"}},
- "MemoryQoS": {},
- "MinDomainsInPodTopologySpread": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.24", RemovedInVersion: "1.32"}},
- "MinimizeIPTablesRestore": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{AddedInVersion: "1.26", RemovedInVersion: "1.30"}},
- "MultiCIDRServiceAllocator": {},
- "MutableCSINodeAllocatableCount": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "MutatingAdmissionPolicy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "NewVolumeManagerReconstruction": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.25", RemovedInVersion: "1.32"}},
- "NFTablesProxyMode": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "NodeInclusionPolicyInPodTopologySpread": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
- "NodeLogQuery": {},
- "NodeOutOfServiceVolumeDetach": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{AddedInVersion: "1.24", RemovedInVersion: "1.32"}},
- "NodeSwap": {},
- "OpenAPIEnums": {},
- "OrderedNamespaceDeletion": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "PDBUnhealthyPodEvictionPolicy": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "PersistentVolumeLastPhaseTransitionTime": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.33"}},
- "PodAndContainerStatsFromCRI": {},
- "PodDeletionCost": {},
- "PodDisruptionConditions": {LockedValue: true, LockedToDefaultInVersion: "1.31"},
- "PodHostIPs": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.32"}},
- "PodIndexLabel": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "PodLevelResources": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "PodLifecycleSleepAction": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "PodLifecycleSleepActionAllowZero": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "PodLogsQuerySplitStreams": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "PodObservedGenerationTracking": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "PodReadyToStartContainersCondition": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "PodSchedulingReadiness": {LockedValue: true, LockedToDefaultInVersion: "1.30"},
- "PodTopologyLabelsAdmission": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "PortForwardWebsockets": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "PreferAlignCpusByUncoreCache": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "PreferSameTrafficDistribution": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "ProcMountType": {},
- "ProxyTerminatingEndpoints": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "QOSReserved": {},
- "ReadWriteOncePod": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "RecoverVolumeExpansionFailure": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "RecursiveReadOnlyMounts": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "ReduceDefaultCrashLoopBackOffDecay": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "RelaxedDNSSearchValidation": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "RelaxedEnvironmentVariableValidation": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "ReloadKubeletServerCertificateFile": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "RemainingItemCount": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "RemoteRequestHeaderUID": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "RemoveSelfLink": {LockedValue: true, LockedToDefaultInVersion: "1.24", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "ResilientWatchCacheInitialization": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "ResourceHealthStatus": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "RetryGenerateName": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "RotateKubeletServerCertificate": {},
- "RuntimeClassInImageCriApi": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "SchedulerAsyncPreemption": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "SchedulerPopFromBackoffQ": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "SchedulerQueueingHints": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "SecurityContextDeny": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
- "SELinuxChangePolicy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "SELinuxMount": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "SELinuxMountReadWriteOncePod": {LockedValue: true, LockedToDefaultInVersion: "1.29"},
- "SeparateCacheWatchRPC": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "SeparateTaintEvictionController": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "ServerSideApply": {LockedValue: true, LockedToDefaultInVersion: "1.22", VersionRange: versionutils.VersionRange{AddedInVersion: "1.14", RemovedInVersion: "1.32"}},
- "ServerSideFieldValidation": {LockedValue: true, LockedToDefaultInVersion: "1.27", VersionRange: versionutils.VersionRange{AddedInVersion: "1.23", RemovedInVersion: "1.32"}},
- "ServiceAccountNodeAudienceRestriction": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "ServiceAccountTokenJTI": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "ServiceAccountTokenNodeBinding": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "ServiceAccountTokenNodeBindingValidation": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "ServiceAccountTokenPodNodeInfo": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "ServiceNodePortStaticSubrange": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
- "ServiceTrafficDistribution": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "SidecarContainers": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "SizeMemoryBackedVolumes": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.20"}},
- "SkipReadOnlyValidationGCE": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.31"}},
- "StableLoadBalancerNodeSet": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.32"}},
- "StatefulSetAutoDeletePVC": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.23"}},
- "StatefulSetStartOrdinal": {LockedValue: true, LockedToDefaultInVersion: "1.31"},
- "StorageCapacityScoring": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "StorageNamespaceIndex": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "StorageVersionAPI": {},
- "StorageVersionHash": {},
- "StorageVersionMigrator": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "StreamingCollectionEncodingToJSON": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "StreamingCollectionEncodingToProtobuf": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "StrictCostEnforcementForVAP": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "StrictCostEnforcementForWebhooks": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "StrictIPCIDRValidation": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
- "StructuredAuthenticationConfiguration": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "StructuredAuthorizationConfiguration": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "SupplementalGroupsPolicy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "SystemdWatchdog": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "TopologyAwareHints": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
- "TopologyManagerPolicyAlphaOptions": {},
- "TopologyManagerPolicyBetaOptions": {},
- "TopologyManagerPolicyOptions": {LockedValue: true, LockedToDefaultInVersion: "1.32"},
- "TranslateStreamCloseWebsocketRequests": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "UnauthenticatedHTTP2DOSMitigation": {},
- "UnknownVersionInteroperabilityProxy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "UserNamespacesPodSecurityStandards": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "UserNamespacesSupport": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
- "ValidatingAdmissionPolicy": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.32"}},
- "VolumeAttributesClass": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
- "VolumeCapacityPriority": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "WatchBookmark": {LockedValue: true, LockedToDefaultInVersion: "1.17", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
- "WatchCacheInitializationPostStartHook": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
- "WatchFromStorageWithoutResourceVersion": {LockedValue: false, LockedToDefaultInVersion: "1.33"},
- "WatchList": {},
- "WatchListClient": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
- "WinDSR": {},
- "WinOverlay": {},
- "WindowsCPUAndMemoryAffinity": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "WindowsGracefulNodeShutdown": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
- "WindowsHostNetwork": {},
- "ZeroLimitedNominalConcurrencyShares": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29", RemovedInVersion: "1.32"}},
+ "AdmissionWebhookMatchConditions": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "AggregatedDiscoveryRemoveBetaType": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "AllowDNSOnlyNodeCSR": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "AllowInsecureKubeletCertificateSigningRequests": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "AllowOverwriteTerminationGracePeriodSeconds": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "AllowServiceLBStatusOnNonLB": {LockedValue: false, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "AllowUnsafeMalformedObjectDeletion": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "AllowParsingUserUIDFromCertAuth": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "APIListChunking": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "APIPriorityAndFairness": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "APIResponseCompression": {},
+ "APISelfSubjectReview": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "APIServerIdentity": {},
+ "APIServerTracing": {LockedValue: true, LockedToDefaultInVersion: "1.34"},
+ "APIServingWithRoutine": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "AggregatedDiscoveryEndpoint": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "AnonymousAuthConfigurableEndpoints": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "AnyVolumeDataSource": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
+ "AppArmor": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "AppArmorFields": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30", RemovedInVersion: "1.33"}},
+ "AuthorizeNodeWithSelectors": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "AuthorizeWithSelectors": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "BtreeWatchCache": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "CBORServingAndStorage": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "ClearingNominatedNodeNameAfterBinding": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "CloudControllerManagerWebhook": {},
+ "CloudDualStackNodeIPs": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.32"}},
+ "ClusterTrustBundle": {},
+ "ClusterTrustBundleProjection": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "ComponentFlagz": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "ComponentSLIs": {},
+ "ComponentStatusz": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "ConcurrentWatchObjectDecode": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "ContainerCheckpoint": {},
+ "ContainerRestartRules": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "ContainerStopSignals": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "ContextualLogging": {LockedValue: true, LockedToDefaultInVersion: "1.30"},
+ "ConsistentHTTPGetHandlers": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.26", RemovedInVersion: "1.31"}},
+ "ConsistentListFromCache": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "CoordinatedLeaderElection": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "CPUManager": {LockedValue: true, LockedToDefaultInVersion: "1.26", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "CPUManagerPolicyAlphaOptions": {},
+ "CPUManagerPolicyBetaOptions": {},
+ "CPUManagerPolicyOptions": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
+ "CRDValidationRatcheting": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "CronJobsScheduledAnnotation": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "CrossNamespaceVolumeDataSource": {},
+ "CSIMigrationAzureFile": {LockedValue: true, LockedToDefaultInVersion: "1.27", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "CSIMigrationPortworx": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
+ "CSIMigrationRBD": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "CSINodeExpandSecret": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "CSIVolumeHealth": {},
+ "CustomCPUCFSQuotaPeriod": {},
+ "CustomResourceFieldSelectors": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "CustomResourceValidationExpressions": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "DeclarativeValidation": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "DeclarativeValidationTakeover": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "DefaultHostNetworkHostPortsInPodTemplates": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.31"}},
+ "DeploymentReplicaSetTerminatingReplicas": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "DetectCacheInconsistency": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "DevicePluginCDIDevices": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.34"}},
+ "DisableAllocatorDualWrite": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "DisableCloudProviders": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "DisableCPUQuotaWithExclusiveCPUs": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "DisableKubeletCloudCredentialProviders": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "DisableNodeKubeProxyVersion": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "DRAAdminAccess": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "DRAConsumableCapacity": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "DRAControlPlaneController": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.26", RemovedInVersion: "1.32"}},
+ "DRADeviceBindingConditions": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "DRADeviceTaints": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "DRAExtendedResource": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "DRAPartitionableDevices": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "DRAPrioritizedList": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "DRAResourceClaimDeviceStatus": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "DRASchedulerFilterTimeout": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "DynamicResourceAllocation": {},
+ "EfficientWatchResumption": {LockedValue: true, LockedToDefaultInVersion: "1.24", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "ElasticIndexedJob": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.34"}},
+ "EnvFiles": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "EventedPLEG": {},
+ "ExecProbeTimeout": {},
+ "ExpandedDNSConfig": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "ExperimentalHostUserNamespaceDefaulting": {LockedValue: false, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "ExternalServiceAccountTokenSigner": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "GitRepoVolumeDriver": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "GracefulNodeShutdown": {},
+ "GracefulNodeShutdownBasedOnPodPriority": {},
+ "HonorPVReclaimPolicy": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
+ "HostnameOverride": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "HPAConfigurableTolerance": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "HPAContainerMetrics": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.20", RemovedInVersion: "1.32"}},
+ "HPAScaleToZero": {},
+ "IPTablesOwnershipCleanup": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "ImageMaximumGCAge": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "ImageVolume": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "InPlacePodVerticalScaling": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.27"}},
+ "InPlacePodVerticalScalingAllocatedStatus": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "InPlacePodVerticalScalingExclusiveCPUs": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "InPlacePodVerticalScalingExclusiveMemory": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "InTreePluginAWSUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "InTreePluginAzureDiskUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "InTreePluginAzureFileUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "InTreePluginGCEUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "InTreePluginOpenStackUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "InTreePluginPortworxUnregister": {},
+ "InTreePluginRBDUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "InTreePluginvSphereUnregister": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "InformerResourceVersion": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "JobBackoffLimitPerIndex": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "JobManagedBy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "JobPodFailurePolicy": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "JobPodReplacementPolicy": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "JobReadyPods": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "JobSuccessPolicy": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "KMSv1": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "KMSv2": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{AddedInVersion: "1.25", RemovedInVersion: "1.32"}},
+ "KMSv2KDF": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.32"}},
+ "KubeletEnsureSecretPulledImages": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "KubeletCgroupDriverFromCRI": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "KubeletCrashLoopBackOffMax": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "KubeletFineGrainedAuthz": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "KubeletInUserNamespace": {},
+ "KubeletPodResources": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "KubeletPodResourcesDynamicResources": {},
+ "KubeletPodResourcesListUseActivePods": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "KubeletPodResourcesGet": {},
+ "KubeletPodResourcesGetAllocatable": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "KubeletPSI": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "KubeletRegistrationGetOnExistsOnly": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "KubeletSeparateDiskGC": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "KubeletServiceAccountTokenForCredentialProviders": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "KubeletTracing": {LockedValue: true, LockedToDefaultInVersion: "1.34"},
+ "KubeProxyDrainingTerminatingNodes": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.33"}},
+ "LegacyServiceAccountTokenCleanUp": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.32"}},
+ "LegacyServiceAccountTokenTracking": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{AddedInVersion: "1.26", RemovedInVersion: "1.30"}},
+ "LegacySidecarContainers": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33", RemovedInVersion: "1.34"}},
+ "LoadBalancerIPMode": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "ListFromCacheSnapshot": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "LocalStorageCapacityIsolationFSQuotaMonitoring": {},
+ "LogarithmicScaleDown": {LockedValue: true, LockedToDefaultInVersion: "1.31"},
+ "MatchLabelKeysInPodAffinity": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "MatchLabelKeysInPodTopologySpread": {},
+ "MatchLabelKeysInPodTopologySpreadSelectorMerge": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "MaxUnavailableStatefulSet": {},
+ "MemoryManager": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.21"}},
+ "MemoryQoS": {},
+ "MinDomainsInPodTopologySpread": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.24", RemovedInVersion: "1.32"}},
+ "MinimizeIPTablesRestore": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{AddedInVersion: "1.26", RemovedInVersion: "1.30"}},
+ "MultiCIDRServiceAllocator": {LockedValue: true, LockedToDefaultInVersion: "1.34"},
+ "MutableCSINodeAllocatableCount": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "MutatingAdmissionPolicy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "NewVolumeManagerReconstruction": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.25", RemovedInVersion: "1.32"}},
+ "NFTablesProxyMode": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "NodeInclusionPolicyInPodTopologySpread": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
+ "NodeLogQuery": {},
+ "NodeOutOfServiceVolumeDetach": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{AddedInVersion: "1.24", RemovedInVersion: "1.32"}},
+ "NodeSwap": {LockedValue: true, LockedToDefaultInVersion: "1.34"},
+ "NominatedNodeNameForExpectation": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "OpenAPIEnums": {},
+ "OrderedNamespaceDeletion": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "PDBUnhealthyPodEvictionPolicy": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "PersistentVolumeLastPhaseTransitionTime": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.33"}},
+ "PodAndContainerStatsFromCRI": {},
+ "PodCertificateRequest": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "PodDeletionCost": {},
+ "PodDisruptionConditions": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.34"}},
+ "PodHostIPs": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.32"}},
+ "PodIndexLabel": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "PodLevelResources": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "PodLifecycleSleepAction": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "PodLifecycleSleepActionAllowZero": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "PodLogsQuerySplitStreams": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "PodObservedGenerationTracking": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "PodReadyToStartContainersCondition": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "PodSchedulingReadiness": {LockedValue: true, LockedToDefaultInVersion: "1.30"},
+ "PodTopologyLabelsAdmission": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "PortForwardWebsockets": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "PreferAlignCpusByUncoreCache": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "PreferSameTrafficDistribution": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "PreventStaticPodAPIReferences": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "ProbeHostPodSecurityStandards": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "ProcMountType": {},
+ "ProxyTerminatingEndpoints": {LockedValue: true, LockedToDefaultInVersion: "1.28", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "QOSReserved": {},
+ "ReadWriteOncePod": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "RecoverVolumeExpansionFailure": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "RecursiveReadOnlyMounts": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "ReduceDefaultCrashLoopBackOffDecay": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "RelaxedDNSSearchValidation": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "RelaxedEnvironmentVariableValidation": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "RelaxedServiceNameValidation": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "ReloadKubeletServerCertificateFile": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "RemainingItemCount": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "RemoteRequestHeaderUID": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "RemoveSelfLink": {LockedValue: true, LockedToDefaultInVersion: "1.24", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "ResilientWatchCacheInitialization": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "ResourceHealthStatus": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "RetryGenerateName": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "RotateKubeletServerCertificate": {},
+ "RuntimeClassInImageCriApi": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "SchedulerAsyncAPICalls": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "SchedulerAsyncPreemption": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "SchedulerPopFromBackoffQ": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "SchedulerQueueingHints": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "SecurityContextDeny": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.30"}},
+ "SELinuxChangePolicy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "SELinuxMount": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "SELinuxMountReadWriteOncePod": {LockedValue: true, LockedToDefaultInVersion: "1.29"},
+ "SeparateCacheWatchRPC": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "SeparateTaintEvictionController": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "ServerSideApply": {LockedValue: true, LockedToDefaultInVersion: "1.22", VersionRange: versionutils.VersionRange{AddedInVersion: "1.14", RemovedInVersion: "1.32"}},
+ "ServerSideFieldValidation": {LockedValue: true, LockedToDefaultInVersion: "1.27", VersionRange: versionutils.VersionRange{AddedInVersion: "1.23", RemovedInVersion: "1.32"}},
+ "ServiceAccountNodeAudienceRestriction": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "ServiceAccountTokenJTI": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "ServiceAccountTokenNodeBinding": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "ServiceAccountTokenNodeBindingValidation": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "ServiceAccountTokenPodNodeInfo": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "ServiceNodePortStaticSubrange": {LockedValue: true, LockedToDefaultInVersion: "1.29", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.31"}},
+ "ServiceTrafficDistribution": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "SidecarContainers": {LockedValue: true, LockedToDefaultInVersion: "1.33", VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "SizeBasedListCostEstimate": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "SizeMemoryBackedVolumes": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.20"}},
+ "SkipReadOnlyValidationGCE": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28", RemovedInVersion: "1.31"}},
+ "StableLoadBalancerNodeSet": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.32"}},
+ "StatefulSetAutoDeletePVC": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.23"}},
+ "StatefulSetStartOrdinal": {LockedValue: true, LockedToDefaultInVersion: "1.31", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.34"}},
+ "StorageCapacityScoring": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "StorageNamespaceIndex": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "StorageVersionAPI": {},
+ "StorageVersionHash": {},
+ "StorageVersionMigrator": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "StreamingCollectionEncodingToJSON": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "StreamingCollectionEncodingToProtobuf": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "StrictCostEnforcementForVAP": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "StrictCostEnforcementForWebhooks": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "StrictIPCIDRValidation": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.33"}},
+ "StructuredAuthenticationConfiguration": {LockedValue: true, LockedToDefaultInVersion: "1.34", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "StructuredAuthenticationConfigurationEgressSelector": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "StructuredAuthorizationConfiguration": {LockedValue: true, LockedToDefaultInVersion: "1.32", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "SupplementalGroupsPolicy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "SystemdWatchdog": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "TokenRequestServiceAccountUIDValidation": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.34"}},
+ "TopologyAwareHints": {LockedValue: true, LockedToDefaultInVersion: "1.33"},
+ "TopologyManagerPolicyAlphaOptions": {},
+ "TopologyManagerPolicyBetaOptions": {},
+ "TopologyManagerPolicyOptions": {LockedValue: true, LockedToDefaultInVersion: "1.32"},
+ "TranslateStreamCloseWebsocketRequests": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "UnauthenticatedHTTP2DOSMitigation": {},
+ "UnknownVersionInteroperabilityProxy": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "UserNamespacesPodSecurityStandards": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "UserNamespacesSupport": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.28"}},
+ "ValidatingAdmissionPolicy": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.32"}},
+ "VolumeAttributesClass": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.29"}},
+ "VolumeCapacityPriority": {VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "WatchBookmark": {LockedValue: true, LockedToDefaultInVersion: "1.17", VersionRange: versionutils.VersionRange{RemovedInVersion: "1.33"}},
+ "WatchCacheInitializationPostStartHook": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.31"}},
+ "WatchFromStorageWithoutResourceVersion": {LockedValue: false, LockedToDefaultInVersion: "1.33"},
+ "WatchList": {},
+ "WatchListClient": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.30"}},
+ "WinDSR": {LockedValue: true, LockedToDefaultInVersion: "1.34"},
+ "WinOverlay": {LockedValue: true, LockedToDefaultInVersion: "1.34"},
+ "WindowsCPUAndMemoryAffinity": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "WindowsGracefulNodeShutdown": {VersionRange: versionutils.VersionRange{AddedInVersion: "1.32"}},
+ "WindowsHostNetwork": {},
+ "ZeroLimitedNominalConcurrencyShares": {LockedValue: true, LockedToDefaultInVersion: "1.30", VersionRange: versionutils.VersionRange{AddedInVersion: "1.29", RemovedInVersion: "1.32"}},
}
// IsFeatureGateSupported returns true if the given feature gate is supported for the given Kubernetes version.
diff --git a/pkg/utils/validation/kubernetesversion/version.go b/pkg/utils/validation/kubernetesversion/version.go
index 2bffe094614..87390240128 100644
--- a/pkg/utils/validation/kubernetesversion/version.go
+++ b/pkg/utils/validation/kubernetesversion/version.go
@@ -18,6 +18,7 @@ var SupportedVersions = []string{
"1.31",
"1.32",
"1.33",
+ "1.34",
}
// CheckIfSupported checks if the provided version is part of the supported Kubernetes versions list.
diff --git a/pkg/utils/validation/kubernetesversion/version_test.go b/pkg/utils/validation/kubernetesversion/version_test.go
index 7a40321fcfb..6900c41e16b 100644
--- a/pkg/utils/validation/kubernetesversion/version_test.go
+++ b/pkg/utils/validation/kubernetesversion/version_test.go
@@ -24,6 +24,7 @@ var _ = Describe("Version", func() {
Entry("1.31", "1.31", Succeed()),
Entry("1.32", "1.32", Succeed()),
Entry("1.33", "1.33", Succeed()),
- Entry("1.34", "1.34", MatchError(ContainSubstring("unsupported kubernetes version"))),
+ Entry("1.34", "1.34", Succeed()),
+ Entry("1.35", "1.35", MatchError(ContainSubstring("unsupported kubernetes version"))),
)
})
From cacc4343cb209d2445430ebd5c8825c508ba7090 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Mon, 3 Nov 2025 18:08:31 +0100
Subject: [PATCH 022/176] Update module github.com/gardener/cert-management to
v0.19.0 (#13327)
---
go.mod | 21 +++++++++++----------
go.sum | 46 ++++++++++++++++++++++++----------------------
2 files changed, 35 insertions(+), 32 deletions(-)
diff --git a/go.mod b/go.mod
index 0f376e35c27..b578bb677c1 100644
--- a/go.mod
+++ b/go.mod
@@ -13,12 +13,12 @@ require (
github.com/distribution/distribution/v3 v3.0.0
github.com/docker/cli v28.5.1+incompatible
github.com/fluent/fluent-operator/v3 v3.3.0
- github.com/gardener/cert-management v0.18.0
+ github.com/gardener/cert-management v0.19.0
github.com/gardener/dependency-watchdog v1.6.0
github.com/gardener/etcd-druid/api v0.33.0
github.com/gardener/machine-controller-manager v0.60.2
github.com/gardener/terminal-controller-manager v0.34.0
- github.com/go-jose/go-jose/v4 v4.1.1
+ github.com/go-jose/go-jose/v4 v4.1.3
github.com/go-logr/logr v1.4.3
github.com/go-test/deep v1.1.0
github.com/gogo/protobuf v1.3.2
@@ -137,10 +137,11 @@ require (
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
- github.com/go-openapi/errors v0.22.0 // indirect
- github.com/go-openapi/jsonpointer v0.21.2 // indirect
- github.com/go-openapi/jsonreference v0.21.0 // indirect
+ github.com/go-openapi/errors v0.22.3 // indirect
+ github.com/go-openapi/jsonpointer v0.22.1 // indirect
+ github.com/go-openapi/jsonreference v0.21.2 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
+ github.com/go-openapi/swag/jsonname v0.25.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gobuffalo/flect v1.0.3 // indirect
@@ -166,7 +167,7 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
- github.com/json-iterator/go v1.1.12 // indirect
+ github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labstack/echo/v4 v4.13.4 // indirect
@@ -175,7 +176,7 @@ require (
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
- github.com/miekg/dns v1.1.67 // indirect
+ github.com/miekg/dns v1.1.68 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -229,7 +230,7 @@ require (
go.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect
go.etcd.io/etcd/client/v3 v3.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
- go.opentelemetry.io/auto/sdk v1.1.0 // indirect
+ go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/collector/featuregate v1.37.0 // indirect
go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 // indirect
go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 // indirect
@@ -267,8 +268,8 @@ require (
golang.org/x/term v0.36.0 // indirect
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
- google.golang.org/grpc v1.75.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
+ google.golang.org/grpc v1.76.0 // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
diff --git a/go.sum b/go.sum
index 4004cecb47d..a33960d6efe 100644
--- a/go.sum
+++ b/go.sum
@@ -15,8 +15,8 @@ cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyT
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/compute v1.28.0 h1:OPtBxMcheSS+DWfci803qvPly3d4w7Eu5ztKBcFfzwk=
-cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU=
-cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
+cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
+cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
@@ -236,8 +236,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
-github.com/gardener/cert-management v0.18.0 h1:s2YhkN8z7lXe9En52GCeqQ9be10uEbLtH/FFAh6BVgQ=
-github.com/gardener/cert-management v0.18.0/go.mod h1:9+JT+EBJB2OIX65EG+P1p/DZ/UJ3W8WR0h40ZjKbw+Q=
+github.com/gardener/cert-management v0.19.0 h1:BNumdw748Pg9798NzxHmmpKuXFRLHSPuvcPKQHOiFcw=
+github.com/gardener/cert-management v0.19.0/go.mod h1:u5OKwiDyUdCuW9vhDV92ozCVkynXUBrYCMHr4rVNiCY=
github.com/gardener/dependency-watchdog v1.6.0 h1:ARCIbcNmhjefmV7ex8ADReeD2MPsEawwT/MoZKTQV/M=
github.com/gardener/dependency-watchdog v1.6.0/go.mod h1:NXkna7bW5O+IGxLAX0KdEaW8yFREDfSHSccuoY+YZu0=
github.com/gardener/etcd-druid/api v0.33.0 h1:YwgsYYldaLig2laJMAAMX/dg9/XsQx/LPz8+iL52V6w=
@@ -254,8 +254,8 @@ github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6O
github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE=
github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
-github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
+github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
+github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@@ -268,18 +268,18 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
-github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
-github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
+github.com/go-openapi/errors v0.22.3 h1:k6Hxa5Jg1TUyZnOwV2Lh81j8ayNw5VVYLvKrp4zFKFs=
+github.com/go-openapi/errors v0.22.3/go.mod h1:+WvbaBBULWCOna//9B9TbLNGSFOfF8lY9dw4hGiEiKQ=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonpointer v0.21.2 h1:AqQaNADVwq/VnkCmQg6ogE+M3FOsKTytwges0JdwVuA=
-github.com/go-openapi/jsonpointer v0.21.2/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
+github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk=
+github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
-github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
-github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
+github.com/go-openapi/jsonreference v0.21.2 h1:Wxjda4M/BBQllegefXrY/9aq1fxBA8sI5M/lFU6tSWU=
+github.com/go-openapi/jsonreference v0.21.2/go.mod h1:pp3PEjIsJ9CZDGCNOyXIQxsNuroxm8FAJ/+quA0yKzQ=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
@@ -287,6 +287,8 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
+github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU=
+github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo=
github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8=
github.com/go-resty/resty/v2 v2.15.3/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@@ -461,8 +463,8 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
-github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 h1:9Nu54bhS/H/Kgo2/7xNSUuC5G28VR8ljfrLKU2G4IjU=
+github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12/go.mod h1:TBzl5BIHNXfS9+C35ZyJaklL7mLDbgUkcgXzSLa8Tk0=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
@@ -511,8 +513,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=
github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=
-github.com/miekg/dns v1.1.67 h1:kg0EHj0G4bfT5/oOys6HhZw4vmMlnoZ+gDu8tJ/AlI0=
-github.com/miekg/dns v1.1.67/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
+github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
+github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@@ -768,8 +770,8 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
-go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
+go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/collector/featuregate v1.37.0 h1:CjsHzjktiqq/dxid4Xkhuf3yD6oB/c7yRBWhokBJqpE=
go.opentelemetry.io/collector/featuregate v1.37.0/go.mod h1:Y/KsHbvREENKvvN9RlpiWk/IGBK+CATBYzIIpU7nccc=
go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 h1:UW0+QyeyBVhn+COBec3nGhfnFe5lwB0ic1JBVjzhk0w=
@@ -1019,8 +1021,8 @@ google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eY
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -1029,8 +1031,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
-google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
+google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
+google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
From 0ac4022d6a12ffece3400c68c217955ef4925942 Mon Sep 17 00:00:00 2001
From: Georgi Baltiev <82998942+georgibaltiev@users.noreply.github.com>
Date: Tue, 4 Nov 2025 08:24:11 +0200
Subject: [PATCH 023/176] Improve input validations for the `SecretBinding` and
`CredentialsBinding` resources (#13258)
* Validate an object reference's name and namespace fields against the DNS 1123 convention.
* fix: reuse existing validation functions and refactor tests with additional values
* add: else block
---
pkg/apis/core/validation/secretbinding.go | 11 ++++
.../core/validation/secretbinding_test.go | 31 ++++++++++-
pkg/apis/core/validation/utils.go | 9 ++++
pkg/apis/core/validation/utils_test.go | 53 ++++++++++++++-----
4 files changed, 89 insertions(+), 15 deletions(-)
diff --git a/pkg/apis/core/validation/secretbinding.go b/pkg/apis/core/validation/secretbinding.go
index 92b39e8f2ef..fb321fe2a24 100644
--- a/pkg/apis/core/validation/secretbinding.go
+++ b/pkg/apis/core/validation/secretbinding.go
@@ -7,6 +7,7 @@ package validation
import (
corev1 "k8s.io/api/core/v1"
apivalidation "k8s.io/apimachinery/pkg/api/validation"
+ "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"github.com/gardener/gardener/pkg/apis/core"
@@ -69,6 +70,16 @@ func validateSecretReferenceOptionalNamespace(ref corev1.SecretReference, fldPat
if len(ref.Name) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "must provide a name"))
+ } else {
+ for _, err := range validation.IsDNS1123Subdomain(ref.Name) {
+ allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), ref.Name, err))
+ }
+ }
+
+ if len(ref.Namespace) > 0 {
+ for _, err := range apivalidation.ValidateNamespaceName(ref.Namespace, false) {
+ allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), ref.Namespace, err))
+ }
}
return allErrs
diff --git a/pkg/apis/core/validation/secretbinding_test.go b/pkg/apis/core/validation/secretbinding_test.go
index 80887c43a21..b1873396f98 100644
--- a/pkg/apis/core/validation/secretbinding_test.go
+++ b/pkg/apis/core/validation/secretbinding_test.go
@@ -76,8 +76,9 @@ var _ = Describe("SecretBinding Validation Tests", func() {
Entry("should forbid SecretBinding with '_' in the name (not a DNS-1123 subdomain)",
metav1.ObjectMeta{Name: "binding_test", Namespace: "garden"},
ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
- "Field": Equal("metadata.name"),
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("metadata.name"),
+ "BadValue": Equal("binding_test"),
}))),
),
)
@@ -104,6 +105,32 @@ var _ = Describe("SecretBinding Validation Tests", func() {
))
})
+ It("should forbid a SecretBinding with invalid secretRef name and namespace", func() {
+ secretBinding.ObjectMeta = metav1.ObjectMeta{
+ Name: "name",
+ Namespace: "namespace",
+ }
+ secretBinding.SecretRef = corev1.SecretReference{
+ Name: "name-non-valid-@",
+ Namespace: "-namespace-non-valid123",
+ }
+ secretBinding.Provider = &core.SecretBindingProvider{}
+
+ errorList := ValidateSecretBinding(secretBinding)
+ Expect(errorList).To(ConsistOf(
+ PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("secretRef.name"),
+ "BadValue": Equal("name-non-valid-@"),
+ })),
+ PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("secretRef.namespace"),
+ "BadValue": Equal("-namespace-non-valid123"),
+ })),
+ ))
+ })
+
It("should forbid empty stated Quota names", func() {
secretBinding.Quotas = []corev1.ObjectReference{
{},
diff --git a/pkg/apis/core/validation/utils.go b/pkg/apis/core/validation/utils.go
index 2adeccc76d8..dc1c35e4c56 100644
--- a/pkg/apis/core/validation/utils.go
+++ b/pkg/apis/core/validation/utils.go
@@ -599,10 +599,19 @@ func ValidateObjectReferenceNameAndNamespace(ref corev1.ObjectReference, fldPath
if len(ref.Name) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "must provide a name"))
+ } else {
+ for _, err := range validation.IsDNS1123Subdomain(ref.Name) {
+ allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), ref.Name, err))
+ }
}
if requireNamespace && len(ref.Namespace) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("namespace"), "must provide a namespace"))
}
+ if len(ref.Namespace) > 0 {
+ for _, err := range apivalidation.ValidateNamespaceName(ref.Namespace, false) {
+ allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), ref.Namespace, err))
+ }
+ }
return allErrs
}
diff --git a/pkg/apis/core/validation/utils_test.go b/pkg/apis/core/validation/utils_test.go
index a0d745cb7cb..6b10a6a8b72 100644
--- a/pkg/apis/core/validation/utils_test.go
+++ b/pkg/apis/core/validation/utils_test.go
@@ -160,6 +160,28 @@ var _ = Describe("Utils tests", func() {
})),
))
})
+
+ It("should deny a non-DNS1123 name", func() {
+ ref := corev1.ObjectReference{Name: "-name-"}
+ Expect(ValidateObjectReferenceNameAndNamespace(ref, fldPath, false)).To(ConsistOf(
+ PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal(fldPath.Child("name").String()),
+ "BadValue": Equal("-name-"),
+ })),
+ ))
+ })
+
+ It("should deny an invalid namespace", func() {
+ ref := corev1.ObjectReference{Name: "name", Namespace: "namespace-123-@"}
+ Expect(ValidateObjectReferenceNameAndNamespace(ref, fldPath, true)).To(ConsistOf(
+ PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal(fldPath.Child("namespace").String()),
+ "BadValue": Equal("namespace-123-@"),
+ })),
+ ))
+ })
})
DescribeTable("#ValidateCredentialsRef",
@@ -180,8 +202,9 @@ var _ = Describe("Utils tests", func() {
corev1.ObjectReference{APIVersion: "v1", Kind: "Secret", Name: "Foo", Namespace: "bar"},
ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
- "Field": Equal("credentialsRef.name"),
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("credentialsRef.name"),
+ "BadValue": Equal("Foo"),
})),
),
),
@@ -189,8 +212,9 @@ var _ = Describe("Utils tests", func() {
corev1.ObjectReference{APIVersion: "security.gardener.cloud/v1alpha1", Kind: "WorkloadIdentity", Name: "foo", Namespace: "bar?"},
ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
- "Field": Equal("credentialsRef.namespace"),
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("credentialsRef.namespace"),
+ "BadValue": Equal("bar?"),
})),
),
),
@@ -253,9 +277,10 @@ var _ = Describe("Utils tests", func() {
Expect(validationResult).
To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
- "Field": Equal("spec.machineImages[0].name"),
- "Detail": ContainSubstring("machine image name must be a qualified name"),
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.machineImages[0].name"),
+ "BadValue": Equal(name),
+ "Detail": ContainSubstring("machine image name must be a qualified name"),
})),
))
} else {
@@ -304,9 +329,10 @@ var _ = Describe("Utils tests", func() {
Expect(validationResult).
To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
- "Field": Equal("spec.machineTypes[0].name"),
- "Detail": ContainSubstring("machine type name must be a qualified name"),
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.machineTypes[0].name"),
+ "BadValue": Equal(name),
+ "Detail": ContainSubstring("machine type name must be a qualified name"),
})),
))
} else {
@@ -330,9 +356,10 @@ var _ = Describe("Utils tests", func() {
Expect(validationResult).
To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
- "Field": Equal("spec.volumeTypes[0].name"),
- "Detail": ContainSubstring("volume type name must be a qualified name"),
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.volumeTypes[0].name"),
+ "BadValue": Equal(name),
+ "Detail": ContainSubstring("volume type name must be a qualified name"),
})),
))
} else {
From 341416d59fc06977fcf0f69ea326b33bd114286b Mon Sep 17 00:00:00 2001
From: Sebastian Stauch
Date: Tue, 4 Nov 2025 10:18:11 +0100
Subject: [PATCH 024/176] If overlay gets disabled delay network deployment
until the control plane is fully operational (#13332)
* when the overlay gets disabled wait with network deployment until controlplane is ready
* don't suppress error
---
.../shoot/shoot/reconciler_reconcile.go | 71 ++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)
diff --git a/pkg/gardenlet/controller/shoot/shoot/reconciler_reconcile.go b/pkg/gardenlet/controller/shoot/shoot/reconciler_reconcile.go
index 5e0afacff4c..97eac950f3d 100644
--- a/pkg/gardenlet/controller/shoot/shoot/reconciler_reconcile.go
+++ b/pkg/gardenlet/controller/shoot/shoot/reconciler_reconcile.go
@@ -6,11 +6,14 @@ package shoot
import (
"context"
+ "encoding/json"
"fmt"
+ "strconv"
"time"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -155,6 +158,11 @@ func (r *Reconciler) runReconcileShootFlow(ctx context.Context, o *operation.Ope
return v1beta1helper.NewWrappedLastErrors(v1beta1helper.FormatLastErrDescription(err), err)
}
+ isOverlayDisablementInProgress, err := isOverlayDisablementInProgress(ctx, o.Shoot.GetInfo(), botanist.SeedClientSet.Client(), botanist.Shoot.ControlPlaneNamespace)
+ if err != nil {
+ return v1beta1helper.NewWrappedLastErrors(v1beta1helper.FormatLastErrDescription(err), err)
+ }
+
var (
g = flow.NewGraph(fmt.Sprintf("Shoot cluster %s", utils.IifString(isRestoring, "restoration", "reconciliation")))
@@ -609,7 +617,7 @@ func (r *Reconciler) runReconcileShootFlow(ctx context.Context, o *operation.Ope
Name: "Deploying shoot network plugin",
Fn: flow.TaskFn(botanist.DeployNetwork).RetryUntilTimeout(defaultInterval, defaultTimeout),
SkipIf: o.Shoot.IsWorkerless,
- Dependencies: flow.NewTaskIDs(deployReferencedResources, waitUntilGardenerResourceManagerReady, waitUntilOperatingSystemConfigReady, deployKubeScheduler, waitUntilShootNamespacesReady),
+ Dependencies: flow.NewTaskIDs(deployReferencedResources, waitUntilGardenerResourceManagerReady, waitUntilOperatingSystemConfigReady, deployKubeScheduler, waitUntilShootNamespacesReady).InsertIf(isOverlayDisablementInProgress, waitUntilControlPlaneReady),
})
waitUntilNetworkIsReady = g.Add(flow.Task{
Name: "Waiting until shoot network plugin has been reconciled",
@@ -1082,3 +1090,64 @@ func shootHasPendingInPlaceUpdateWorkers(shoot *gardencorev1beta1.Shoot) bool {
return shoot.Status.InPlaceUpdates != nil && shoot.Status.InPlaceUpdates.PendingWorkerUpdates != nil &&
(len(shoot.Status.InPlaceUpdates.PendingWorkerUpdates.AutoInPlaceUpdate) > 0 || len(shoot.Status.InPlaceUpdates.PendingWorkerUpdates.ManualInPlaceUpdate) > 0)
}
+
+func isOverlayDisablementInProgress(ctx context.Context, shoot *gardencorev1beta1.Shoot, seedClient client.Client, shootControlPlaneNamespace string) (bool, error) {
+ shootOverlayEnabled, err := getOverlayEnabledFromShootSpec(shoot)
+ if err != nil {
+ return false, fmt.Errorf("failed to get overlay enabled status from shoot spec: %w", err)
+ }
+
+ networkObj := &extensionsv1alpha1.Network{}
+ if err = seedClient.Get(ctx, client.ObjectKey{Name: shoot.Name, Namespace: shootControlPlaneNamespace}, networkObj); err != nil {
+ // If network doesn't exist yet, no switch in progress
+ if apierrors.IsNotFound(err) {
+ return false, nil
+ }
+
+ return false, fmt.Errorf("failed to get network object: %w", err)
+ }
+
+ networkOverlayEnabled, err := getOverlayEnabledFromProviderConfig(networkObj.Spec.ProviderConfig)
+ if err != nil {
+ return false, fmt.Errorf("failed to get overlay enabled status from provider config: %w", err)
+ }
+
+ // If settings differ, overlay switch is in progress - need to wait for control plane
+ return !shootOverlayEnabled && networkOverlayEnabled, nil
+}
+
+func getOverlayEnabledFromShootSpec(shoot *gardencorev1beta1.Shoot) (bool, error) {
+ if shoot.Spec.Networking == nil || shoot.Spec.Networking.ProviderConfig == nil {
+ return true, nil
+ }
+
+ return getOverlayEnabledFromProviderConfig(shoot.Spec.Networking.ProviderConfig)
+}
+
+func getOverlayEnabledFromProviderConfig(providerConfig *runtime.RawExtension) (bool, error) {
+ if providerConfig == nil {
+ return true, nil
+ }
+
+ var config map[string]interface{}
+ if err := json.Unmarshal(providerConfig.Raw, &config); err != nil {
+ return false, fmt.Errorf("failed to unmarshal provider config: %w", err)
+ }
+
+ if overlay, exists := config["overlay"]; exists {
+ if overlayMap, ok := overlay.(map[string]interface{}); ok {
+ if enabled, exists := overlayMap["enabled"]; exists {
+ if enabledStr, ok := enabled.(string); ok {
+ enabledBool, err := strconv.ParseBool(enabledStr)
+ if err != nil {
+ return false, fmt.Errorf("failed to get overlay enabled status from provider config: %w", err)
+ }
+
+ return enabledBool, nil
+ }
+ }
+ }
+ }
+
+ return true, nil
+}
From 7efe7d8fc9a12ed13608c4f1a035029cb97fdc7c Mon Sep 17 00:00:00 2001
From: Marin Atanasov Nikolov
Date: Tue, 4 Nov 2025 12:37:11 +0200
Subject: [PATCH 025/176] docs: Add link to GEP-34 and fix file name (#13336)
* docs: typo fix in GEP file name
* docs: add link to GEP-34
---
docs/README.md | 1 +
...34-observability2.0-opentelemetry-operator-and-collectors.md} | 0
2 files changed, 1 insertion(+)
rename docs/proposals/{34-observability2.0-opentelemtry-operator-and-collectors.md => 34-observability2.0-opentelemetry-operator-and-collectors.md} (100%)
diff --git a/docs/README.md b/docs/README.md
index f1e13e09bc3..ce088f725dd 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -159,6 +159,7 @@
* [GEP-31: In-Place Node Updates of Shoot Clusters](proposals/31-inplace-node-update.md)
* [GEP-32: Cloud Profile Version Classification Lifecycles](proposals/32-version-classification-lifecycles.md)
* [GEP-33: Machine Image Capabilities](proposals/33-machine-image-capabilities.md)
+* [GEP-34: Introducing OpenTelemetry Operator and Collectors in Shoot Control Planes](proposals/34-observability2.0-opentelemetry-operator-and-collectors.md)
## Development
diff --git a/docs/proposals/34-observability2.0-opentelemtry-operator-and-collectors.md b/docs/proposals/34-observability2.0-opentelemetry-operator-and-collectors.md
similarity index 100%
rename from docs/proposals/34-observability2.0-opentelemtry-operator-and-collectors.md
rename to docs/proposals/34-observability2.0-opentelemetry-operator-and-collectors.md
From 616d40532042b9d1083eec1bd830d2a9824ea2b0 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Tue, 4 Nov 2025 13:19:07 +0100
Subject: [PATCH 026/176] Update
registry.k8s.io/ingress-nginx/controller-chroot Docker tag to v1.14.0
(#13319)
* Update registry.k8s.io/ingress-nginx/controller-chroot Docker tag to v1.14.0
* chore: Add targetVersion constraints for nginx-ingress-controller image
According to: https://github.com/kubernetes/ingress-nginx#supported-versions-table
---------
Co-authored-by: Marc Vornetran
---
imagevector/containers.yaml | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index 2de27c9cfdd..c1fccbb350f 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -83,10 +83,25 @@ images:
sourceRepository: github.com/gardener/dependency-watchdog
repository: europe-docker.pkg.dev/gardener-project/releases/gardener/dependency-watchdog
tag: "v1.6.0"
+ - name: nginx-ingress-controller
+ sourceRepository: github.com/kubernetes/ingress-nginx
+ repository: registry.k8s.io/ingress-nginx/controller-chroot
+ tag: "v1.14.0"
+ targetVersion: ">= 1.30"
+ labels:
+ - name: 'gardener.cloud/cve-categorisation'
+ value:
+ network_exposure: 'public'
+ authentication_enforced: true
+ user_interaction: 'end-user'
+ confidentiality_requirement: 'high'
+ integrity_requirement: 'high'
+ availability_requirement: 'low'
- name: nginx-ingress-controller
sourceRepository: github.com/kubernetes/ingress-nginx
repository: registry.k8s.io/ingress-nginx/controller-chroot
tag: "v1.13.4"
+ targetVersion: "1.29.x"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
From f0408765fc72c469725d53ad4d6fb1b27724a5ea Mon Sep 17 00:00:00 2001
From: Johannes Scheerer
Date: Tue, 4 Nov 2025 13:19:16 +0100
Subject: [PATCH 027/176] Fix timing issue in bootstrap token test (#13337)
---
pkg/utils/kubernetes/bootstraptoken/bootstraptoken_test.go | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/pkg/utils/kubernetes/bootstraptoken/bootstraptoken_test.go b/pkg/utils/kubernetes/bootstraptoken/bootstraptoken_test.go
index fee62ea0e82..62b140a8822 100644
--- a/pkg/utils/kubernetes/bootstraptoken/bootstraptoken_test.go
+++ b/pkg/utils/kubernetes/bootstraptoken/bootstraptoken_test.go
@@ -16,6 +16,7 @@ import (
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
. "github.com/gardener/gardener/pkg/utils/kubernetes/bootstraptoken"
+ "github.com/gardener/gardener/pkg/utils/test"
)
var _ = Describe("bootstraptoken", func() {
@@ -30,6 +31,7 @@ var _ = Describe("bootstraptoken", func() {
BeforeEach(func() {
fakeClient = fakeclient.NewClientBuilder().Build()
+ DeferCleanup(test.WithVar(&Now, func() metav1.Time { return metav1.NewTime(time.Date(2050, 5, 5, 5, 5, 5, 0, time.UTC)) }))
})
Describe("#ComputeBootstrapToken", func() {
@@ -44,7 +46,7 @@ var _ = Describe("bootstraptoken", func() {
HaveKeyWithValue("token-id", Equal([]byte(tokenID))),
HaveKeyWithValue("token-secret", HaveLen(16)),
HaveKeyWithValue("description", Equal([]byte(description))),
- HaveKeyWithValue("expiration", Equal([]byte(metav1.Now().Add(validity).Format(time.RFC3339)))),
+ HaveKeyWithValue("expiration", Equal([]byte(Now().Add(validity).Format(time.RFC3339)))),
HaveKeyWithValue("usage-bootstrap-authentication", Equal([]byte("true"))),
HaveKeyWithValue("usage-bootstrap-signing", Equal([]byte("true"))),
))
@@ -75,7 +77,7 @@ var _ = Describe("bootstraptoken", func() {
HaveKeyWithValue("token-id", Equal([]byte(tokenID))),
HaveKeyWithValue("token-secret", Equal([]byte(tokenSecret))),
HaveKeyWithValue("description", Equal([]byte(description))),
- HaveKeyWithValue("expiration", Equal([]byte(metav1.Now().Add(validity).Format(time.RFC3339)))),
+ HaveKeyWithValue("expiration", Equal([]byte(Now().Add(validity).Format(time.RFC3339)))),
HaveKeyWithValue("usage-bootstrap-authentication", Equal([]byte("true"))),
HaveKeyWithValue("usage-bootstrap-signing", Equal([]byte("true"))),
))
From e8741ee1574c38b220deba0cd1d20021b68b081c Mon Sep 17 00:00:00 2001
From: Ashwani Kumar
Date: Tue, 4 Nov 2025 20:11:06 +0530
Subject: [PATCH 028/176] Remove ambiguity in CP health reporting when DWD
prober scales down certain deployments (#13338)
* Remove ambiguity in CP health reporting when DWD prober scales down
* Addressed review comments
---
pkg/gardenlet/controller/shoot/care/health.go | 4 ++--
pkg/gardenlet/controller/shoot/care/health_test.go | 10 ++++++++--
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/pkg/gardenlet/controller/shoot/care/health.go b/pkg/gardenlet/controller/shoot/care/health.go
index 42fd14a571e..48583f486d8 100644
--- a/pkg/gardenlet/controller/shoot/care/health.go
+++ b/pkg/gardenlet/controller/shoot/care/health.go
@@ -418,7 +418,7 @@ func (h *Health) checkControlPlane(
if scaledDownDeploymentNames, err := CheckIfDependencyWatchdogProberScaledDownControllers(ctx, h.seedClient.Client(), h.shoot.ControlPlaneNamespace); err != nil {
return ptr.To(v1beta1helper.FailedCondition(h.clock, h.shoot.GetInfo().Status.LastOperation, h.conditionThresholds, condition, "ControllersScaledDownCheckError", err.Error())), nil
} else if len(scaledDownDeploymentNames) > 0 {
- return ptr.To(v1beta1helper.FailedCondition(h.clock, h.shoot.GetInfo().Status.LastOperation, h.conditionThresholds, condition, "ControllersScaledDown", fmt.Sprintf("The following deployments have been scaled down to 0 replicas (perhaps by dependency-watchdog-prober): %s", strings.Join(scaledDownDeploymentNames, ", ")))), nil
+ return ptr.To(v1beta1helper.FailedCondition(h.clock, h.shoot.GetInfo().Status.LastOperation, h.conditionThresholds, condition, "ControllersScaledDown", fmt.Sprintf("The following deployments have been scaled down to 0 replicas by dependency-watchdog-prober: %s", strings.Join(scaledDownDeploymentNames, ", ")))), nil
}
}
@@ -457,7 +457,7 @@ func CheckIfDependencyWatchdogProberScaledDownControllers(ctx context.Context, s
return nil, fmt.Errorf("failed reading Deployment %s for scale-down check: %w", deployment.Name, err)
}
- if ptr.Deref(deployment.Spec.Replicas, 0) == 0 {
+ if _, ok := deployment.Annotations["dependency-watchdog.gardener.cloud/meltdown-protection-active"]; ok {
scaledDownDeploymentNames = append(scaledDownDeploymentNames, deployment.Name)
}
}
diff --git a/pkg/gardenlet/controller/shoot/care/health_test.go b/pkg/gardenlet/controller/shoot/care/health_test.go
index a91e6cb236b..587466bf4aa 100644
--- a/pkg/gardenlet/controller/shoot/care/health_test.go
+++ b/pkg/gardenlet/controller/shoot/care/health_test.go
@@ -869,17 +869,23 @@ var _ = Describe("health check", func() {
Expect(scaledDownDeploymentNames).To(BeEmpty())
})
- It("should report names because some relevant deployment have replicas == 0", func() {
+ It("should report names because some relevant deployment have replicas == 0 and meltdown annotation is set", func() {
deploymentKCM.Spec.Replicas = nil
deploymentMCM.Spec.Replicas = ptr.To[int32](0)
+ // Set meltdown annotation only on deploymentMCM
+ if deploymentMCM.Annotations == nil {
+ deploymentMCM.Annotations = map[string]string{}
+ }
+ deploymentMCM.Annotations["dependency-watchdog.gardener.cloud/meltdown-protection-active"] = ""
+
Expect(fakeClient.Create(ctx, deploymentCA)).To(Succeed())
Expect(fakeClient.Create(ctx, deploymentKCM)).To(Succeed())
Expect(fakeClient.Create(ctx, deploymentMCM)).To(Succeed())
scaledDownDeploymentNames, err := CheckIfDependencyWatchdogProberScaledDownControllers(ctx, fakeClient, controlPlaneNamespace)
Expect(err).NotTo(HaveOccurred())
- Expect(scaledDownDeploymentNames).To(HaveExactElements(deploymentKCM.Name, deploymentMCM.Name))
+ Expect(scaledDownDeploymentNames).To(HaveExactElements(deploymentMCM.Name))
})
})
From f34fc0bfb2d272d02d2afbb0dc24d25c74a2a33f Mon Sep 17 00:00:00 2001
From: Viktor
Date: Tue, 4 Nov 2025 18:36:08 +0200
Subject: [PATCH 029/176] Revert "support server block imports for
node-local-dns (#13160)" (#13344)
This reverts commit 0acc41c6ef96a5e93976651df430e9bce3b9d870.
---
docs/usage/networking/custom-dns-config.md | 6 +-
docs/usage/networking/node-local-dns.md | 2 +-
imagevector/containers.go | 2 -
imagevector/containers.yaml | 17 -----
pkg/component/networking/coredns/coredns.go | 5 +-
.../networking/nodelocaldns/nodelocaldns.go | 19 +++---
.../nodelocaldns/nodelocaldns_test.go | 53 +---------------
.../networking/nodelocaldns/resources.go | 63 ++-----------------
.../operation/botanist/nodelocaldns.go | 20 +++---
.../controller/dnsrecord/actuator.go | 3 +-
.../controller/dnsrecord/actuator_test.go | 5 +-
skaffold-gardenadm.yaml | 2 -
skaffold-operator.yaml | 2 -
skaffold.yaml | 2 -
14 files changed, 28 insertions(+), 173 deletions(-)
diff --git a/docs/usage/networking/custom-dns-config.md b/docs/usage/networking/custom-dns-config.md
index 61cf672ad9d..706f162f69c 100644
--- a/docs/usage/networking/custom-dns-config.md
+++ b/docs/usage/networking/custom-dns-config.md
@@ -102,9 +102,9 @@ This should bring the cluster DNS back to functioning state.
## Node Local DNS
-Starting with Gardener v1.131, custom DNS configurations are fully supported in NodeLocalDNS. In this version, the `coredns-custom` `ConfigMap` is mounted into the NodeLocalDNS pod, allowing custom override and server configurations to be imported into the DNS server. The server configuration is read by a sidecar container and a new configuration file with the correct bind statement and port mappings is generated and imported into NodeLocalDNS pods. Prior to Gardener v1.131, custom DNS configurations might not function as expected with NodeLocalDNS.
-With NodeLocalDNS, ordinary DNS queries targeting upstream DNS servers (i.e., non-Kubernetes domains) are sent directly to the upstream DNS server, bypassing CoreDNS. Therefore, configurations for non-Kubernetes entities, such as the `istio.server` block in the [custom DNS configuration](custom-dns-config.md) example, may not have any effect when NodeLocalDNS is enabled on landscapes with Gardener prior to v1.131.
-If you require custom DNS configurations for non-Kubernetes domains, you need to disable forwarding to upstream DNS with Gardener v1.130 and below. This can be done by setting the `disableForwardToUpstreamDNS` option in the Shoot resource to `true`:
+Starting with Gardener v1.128, custom DNS configurations are fully supported in NodeLocalDNS. In this version, the `coredns-custom` `ConfigMap` is mounted into the NodeLocalDNS pod, allowing custom override and server configurations to be imported into the DNS server. Prior to Gardener v1.128, custom DNS configurations might not function as expected with NodeLocalDNS.
+With NodeLocalDNS, ordinary DNS queries targeting upstream DNS servers (i.e., non-Kubernetes domains) are sent directly to the upstream DNS server, bypassing CoreDNS. Therefore, configurations for non-Kubernetes entities, such as the `istio.server` block in the [custom DNS configuration](custom-dns-config.md) example, may not have any effect when NodeLocalDNS is enabled on landscapes with Gardener prior to v1.128.
+If you require custom DNS configurations for non-Kubernetes domains, you need to disable forwarding to upstream DNS with Gardener v1.127 and below. This can be done by setting the `disableForwardToUpstreamDNS` option in the Shoot resource to `true`:
```yaml
...
spec:
diff --git a/docs/usage/networking/node-local-dns.md b/docs/usage/networking/node-local-dns.md
index 4585a04d729..ca95fa01af6 100644
--- a/docs/usage/networking/node-local-dns.md
+++ b/docs/usage/networking/node-local-dns.md
@@ -48,5 +48,5 @@ For more information about `node-local-dns`, please refer to the [KEP](https://g
## Known Issues
-Custom DNS configuration may not work as expected in conjunction with `NodeLocalDNS` prior to gardener v1.131.
+Custom DNS configuration may not work as expected in conjunction with `NodeLocalDNS` prior to gardener v1.128.
Please refer to [Custom DNS Configuration](custom-dns-config.md#node-local-dns).
diff --git a/imagevector/containers.go b/imagevector/containers.go
index 0ea93ce1eab..c655a64e28e 100644
--- a/imagevector/containers.go
+++ b/imagevector/containers.go
@@ -25,8 +25,6 @@ const (
ContainerImageNameConfigmapReloader = "configmap-reloader"
// ContainerImageNameCoredns is a constant for an image in the image vector with name 'coredns'.
ContainerImageNameCoredns = "coredns"
- // ContainerImageNameCorednsConfigAdapter is a constant for an image in the image vector with name 'coredns-config-adapter'.
- ContainerImageNameCorednsConfigAdapter = "coredns-config-adapter"
// ContainerImageNameCortex is a constant for an image in the image vector with name 'cortex'.
ContainerImageNameCortex = "cortex"
// ContainerImageNameDependencyWatchdog is a constant for an image in the image vector with name 'dependency-watchdog'.
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index c1fccbb350f..585af4b3f6a 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -494,23 +494,6 @@ images:
value:
- type: 'githubTeam'
teamname: 'gardener/gardener-core-networking-maintainers'
- - name: coredns-config-adapter
- sourceRepository: github.com/gardener/coredns-config-adapter
- repository: europe-docker.pkg.dev/gardener-project/releases/gardener/coredns-config-adapter
- tag: "v0.3.0"
- labels:
- - name: 'gardener.cloud/cve-categorisation'
- value:
- network_exposure: 'private'
- authentication_enforced: false
- user_interaction: 'end-user'
- confidentiality_requirement: 'low'
- integrity_requirement: 'high'
- availability_requirement: 'high'
- - name: 'cloud.gardener.cnudie/responsibles'
- value:
- - type: 'githubTeam'
- teamname: 'gardener/gardener-core-networking-maintainers'
- name: node-problem-detector
sourceRepository: github.com/kubernetes/node-problem-detector
repository: registry.k8s.io/node-problem-detector/node-problem-detector
diff --git a/pkg/component/networking/coredns/coredns.go b/pkg/component/networking/coredns/coredns.go
index e5db3bcaa4a..68175e44986 100644
--- a/pkg/component/networking/coredns/coredns.go
+++ b/pkg/component/networking/coredns/coredns.go
@@ -55,9 +55,6 @@ const (
containerName = "coredns"
serviceName = "kube-dns" // this is due to legacy reasons
- // CustomConfigMapName is the name of the custom CoreDNS ConfigMap.
- CustomConfigMapName = "coredns-custom"
-
portNameMetrics = "metrics"
portMetrics = 9153
@@ -322,7 +319,7 @@ import custom/*.server
configMapCustom = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
- Name: CustomConfigMapName,
+ Name: "coredns-custom",
Namespace: metav1.NamespaceSystem,
Annotations: map[string]string{resourcesv1alpha1.Ignore: "true"},
},
diff --git a/pkg/component/networking/nodelocaldns/nodelocaldns.go b/pkg/component/networking/nodelocaldns/nodelocaldns.go
index 52891283d63..571c70e10b5 100644
--- a/pkg/component/networking/nodelocaldns/nodelocaldns.go
+++ b/pkg/component/networking/nodelocaldns/nodelocaldns.go
@@ -64,8 +64,6 @@ const (
metricsPortName = "metrics"
errorMetricsPortName = "errormetrics"
- sideCarName = "coredns-config-adapter"
-
domain = gardencorev1beta1.DefaultDomain
serviceName = "kube-dns-upstream"
livenessProbePort = 8099
@@ -76,14 +74,13 @@ const (
daemonSetPollInterval = 5 * time.Second
- volumeMountNameCleanUp = "cleanup-script"
- volumeMountPathCleanUp = "/scripts"
- volumeMountNameXtablesLock = "xtables-lock"
- volumeMountPathXtablesLock = "/run/xtables.lock"
- volumeMountPathCustomConfig = "/etc/custom"
- volumeMountNameCustomConfig = "custom-config-volume"
- volumeMountNameGeneratedConfig = "generated-config"
- volumeMountPathGeneratedConfig = "/etc/generated-config"
+ volumeMountNameCleanUp = "cleanup-script"
+ volumeMountPathCleanUp = "/scripts"
+ volumeMountNameXtablesLock = "xtables-lock"
+ volumeMountPathXtablesLock = "/run/xtables.lock"
+ volumeMountPathCustomConfig = "/etc/custom"
+ volumeMountNameCustomConfig = "custom-config-volume"
+ customConfigMapName = "coredns-custom"
)
var (
@@ -106,8 +103,6 @@ type Values struct {
Image string
// AlpineImage is the container image used for the cleanup DaemonSet.
AlpineImage string
- // CorednsConfigAdapterImage is the container image used for the coredns config adapter sidecar.
- CorednsConfigAdapterImage string
// VPAEnabled marks whether VerticalPodAutoscaler is enabled for the shoot.
VPAEnabled bool
// Config is the node local configuration for the shoot spec
diff --git a/pkg/component/networking/nodelocaldns/nodelocaldns_test.go b/pkg/component/networking/nodelocaldns/nodelocaldns_test.go
index 2a0ff6eeed3..3518128667c 100644
--- a/pkg/component/networking/nodelocaldns/nodelocaldns_test.go
+++ b/pkg/component/networking/nodelocaldns/nodelocaldns_test.go
@@ -31,7 +31,6 @@ import (
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
"github.com/gardener/gardener/pkg/client/kubernetes"
"github.com/gardener/gardener/pkg/component"
- "github.com/gardener/gardener/pkg/component/networking/coredns"
. "github.com/gardener/gardener/pkg/component/networking/nodelocaldns"
"github.com/gardener/gardener/pkg/resourcemanager/controller/garbagecollector/references"
"github.com/gardener/gardener/pkg/utils"
@@ -351,7 +350,6 @@ data:
cache 30
reload
}
- import generated-config/custom-server-block.server
immutable: true
kind: ConfigMap
metadata:
@@ -453,41 +451,6 @@ status:
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
},
- InitContainers: []corev1.Container{
- {
- Name: "coredns-config-adapter",
- Image: values.CorednsConfigAdapterImage,
- Resources: corev1.ResourceRequirements{
- Requests: corev1.ResourceList{
- corev1.ResourceCPU: resource.MustParse("5m"),
- corev1.ResourceMemory: resource.MustParse("10Mi"),
- },
- },
- SecurityContext: &corev1.SecurityContext{
- AllowPrivilegeEscalation: ptr.To(false),
- RunAsNonRoot: ptr.To(true),
- RunAsUser: ptr.To[int64](65532),
- RunAsGroup: ptr.To[int64](65532),
- },
- Args: []string{
- "-inputDir=/etc/custom",
- "-outputDir=/etc/generated-config",
- "-bind=bind " + bindIP(values),
- },
- VolumeMounts: []corev1.VolumeMount{
- {
- Name: "custom-config-volume",
- MountPath: "/etc/custom",
- ReadOnly: true,
- },
- {
- MountPath: "/etc/generated-config",
- Name: "generated-config",
- },
- },
- RestartPolicy: ptr.To(corev1.ContainerRestartPolicyAlways),
- },
- },
Containers: []corev1.Container{
{
Name: "node-cache",
@@ -569,10 +532,6 @@ status:
MountPath: "/etc/custom",
ReadOnly: true,
},
- {
- MountPath: "/etc/generated-config",
- Name: "generated-config",
- },
},
},
},
@@ -618,19 +577,13 @@ status:
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
- Name: coredns.CustomConfigMapName,
+ Name: "coredns-custom",
},
DefaultMode: ptr.To[int32](420),
Optional: ptr.To(true),
},
},
},
- {
- Name: "generated-config",
- VolumeSource: corev1.VolumeSource{
- EmptyDir: &corev1.EmptyDirVolumeSource{},
- },
- },
},
},
},
@@ -648,8 +601,6 @@ spec:
containerPolicies:
- containerName: '*'
controlledValues: RequestsOnly
- - containerName: coredns-config-adapter
- mode: "Off"
targetRef:
apiVersion: apps/v1
kind: DaemonSet
@@ -769,7 +720,6 @@ ip6.arpa:53 {
cache 30
reload
}
-import generated-config/custom-server-block.server
`,
}
configMapHash = utils.ComputeConfigMapChecksum(configMapData)[:8]
@@ -1044,7 +994,6 @@ ip6.arpa:53 {
cache 30
reload
}
-import generated-config/custom-server-block.server
`,
}
configMapHash = utils.ComputeConfigMapChecksum(configMapData)[:8]
diff --git a/pkg/component/networking/nodelocaldns/resources.go b/pkg/component/networking/nodelocaldns/resources.go
index b184a9ef61b..78fdf7ecd4d 100644
--- a/pkg/component/networking/nodelocaldns/resources.go
+++ b/pkg/component/networking/nodelocaldns/resources.go
@@ -21,7 +21,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
- "github.com/gardener/gardener/pkg/component/networking/coredns"
nodelocaldnsconstants "github.com/gardener/gardener/pkg/component/networking/nodelocaldns/constants"
"github.com/gardener/gardener/pkg/resourcemanager/controller/garbagecollector/references"
kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
@@ -101,7 +100,6 @@ ip6.arpa:53 {
cache 30
reload
}
-import generated-config/custom-server-block.server
`,
},
}
@@ -210,41 +208,6 @@ func (n *nodeLocalDNS) computePoolResourcesData(serviceAccount *corev1.ServiceAc
v1beta1constants.LabelNodeLocalDNS: "true",
v1beta1constants.LabelWorkerPool: worker.Name,
},
- InitContainers: []corev1.Container{
- {
- Name: sideCarName,
- Image: n.values.CorednsConfigAdapterImage,
- Resources: corev1.ResourceRequirements{
- Requests: corev1.ResourceList{
- corev1.ResourceCPU: resource.MustParse("5m"),
- corev1.ResourceMemory: resource.MustParse("10Mi"),
- },
- },
- SecurityContext: &corev1.SecurityContext{
- AllowPrivilegeEscalation: ptr.To(false),
- RunAsNonRoot: ptr.To(true),
- RunAsUser: ptr.To[int64](65532),
- RunAsGroup: ptr.To[int64](65532),
- },
- Args: []string{
- "-inputDir=" + volumeMountPathCustomConfig,
- "-outputDir=" + volumeMountPathGeneratedConfig,
- "-bind=bind " + n.bindIP(),
- },
- VolumeMounts: []corev1.VolumeMount{
- {
- Name: volumeMountNameCustomConfig,
- MountPath: volumeMountPathCustomConfig,
- ReadOnly: true,
- },
- {
- MountPath: volumeMountPathGeneratedConfig,
- Name: volumeMountNameGeneratedConfig,
- },
- },
- RestartPolicy: ptr.To(corev1.ContainerRestartPolicyAlways),
- },
- },
Containers: []corev1.Container{
{
Name: containerName,
@@ -326,10 +289,6 @@ func (n *nodeLocalDNS) computePoolResourcesData(serviceAccount *corev1.ServiceAc
MountPath: volumeMountPathCustomConfig,
ReadOnly: true,
},
- {
- MountPath: volumeMountPathGeneratedConfig,
- Name: volumeMountNameGeneratedConfig,
- },
},
},
},
@@ -375,19 +334,13 @@ func (n *nodeLocalDNS) computePoolResourcesData(serviceAccount *corev1.ServiceAc
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
- Name: coredns.CustomConfigMapName,
+ Name: customConfigMapName,
},
DefaultMode: ptr.To[int32](420),
Optional: ptr.To(true),
},
},
},
- {
- Name: volumeMountNameGeneratedConfig,
- VolumeSource: corev1.VolumeSource{
- EmptyDir: &corev1.EmptyDirVolumeSource{},
- },
- },
},
},
},
@@ -413,16 +366,10 @@ func (n *nodeLocalDNS) computePoolResourcesData(serviceAccount *corev1.ServiceAc
UpdateMode: &vpaUpdateMode,
},
ResourcePolicy: &vpaautoscalingv1.PodResourcePolicy{
- ContainerPolicies: []vpaautoscalingv1.ContainerResourcePolicy{
- {
- ContainerName: vpaautoscalingv1.DefaultContainerResourcePolicy,
- ControlledValues: ptr.To(vpaautoscalingv1.ContainerControlledValuesRequestsOnly),
- },
- {
- ContainerName: sideCarName,
- Mode: ptr.To(vpaautoscalingv1.ContainerScalingModeOff),
- },
- },
+ ContainerPolicies: []vpaautoscalingv1.ContainerResourcePolicy{{
+ ContainerName: vpaautoscalingv1.DefaultContainerResourcePolicy,
+ ControlledValues: ptr.To(vpaautoscalingv1.ContainerControlledValuesRequestsOnly),
+ }},
},
},
}
diff --git a/pkg/gardenlet/operation/botanist/nodelocaldns.go b/pkg/gardenlet/operation/botanist/nodelocaldns.go
index 4691d8715e3..f1ab2b75b73 100644
--- a/pkg/gardenlet/operation/botanist/nodelocaldns.go
+++ b/pkg/gardenlet/operation/botanist/nodelocaldns.go
@@ -35,23 +35,17 @@ func (b *Botanist) DefaultNodeLocalDNS() (nodelocaldns.Interface, error) {
return nil, err
}
- imageCorednsConfigAdapter, err := imagevector.Containers().FindImage(imagevector.ContainerImageNameCorednsConfigAdapter)
- if err != nil {
- return nil, err
- }
-
return nodelocaldns.New(
b.SeedClientSet.Client(),
b.Shoot.ControlPlaneNamespace,
nodelocaldns.Values{
- Image: image.String(),
- AlpineImage: imageAlpine.String(),
- CorednsConfigAdapterImage: imageCorednsConfigAdapter.String(),
- VPAEnabled: b.Shoot.WantsVerticalPodAutoscaler,
- Config: v1beta1helper.GetNodeLocalDNS(b.Shoot.GetInfo().Spec.SystemComponents),
- Workers: b.Shoot.GetInfo().Spec.Provider.Workers,
- KubeProxyConfig: b.Shoot.GetInfo().Spec.Kubernetes.KubeProxy,
- Log: b.Logger,
+ Image: image.String(),
+ AlpineImage: imageAlpine.String(),
+ VPAEnabled: b.Shoot.WantsVerticalPodAutoscaler,
+ Config: v1beta1helper.GetNodeLocalDNS(b.Shoot.GetInfo().Spec.SystemComponents),
+ Workers: b.Shoot.GetInfo().Spec.Provider.Workers,
+ KubeProxyConfig: b.Shoot.GetInfo().Spec.Kubernetes.KubeProxy,
+ Log: b.Logger,
},
), nil
}
diff --git a/pkg/provider-local/controller/dnsrecord/actuator.go b/pkg/provider-local/controller/dnsrecord/actuator.go
index 905d40f3207..a12611e09d7 100644
--- a/pkg/provider-local/controller/dnsrecord/actuator.go
+++ b/pkg/provider-local/controller/dnsrecord/actuator.go
@@ -21,7 +21,6 @@ import (
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
- "github.com/gardener/gardener/pkg/component/networking/coredns"
)
// Actuator implements the DNSRecord actuator for the local DNS provider.
@@ -86,7 +85,7 @@ func (a *Actuator) Restore(ctx context.Context, log logr.Logger, dnsRecord *exte
}
func (a *Actuator) patchCoreDNSConfigMap(ctx context.Context, mutate func(configMap *corev1.ConfigMap)) error {
- configMap := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: coredns.CustomConfigMapName, Namespace: "gardener-extension-provider-local-coredns"}}
+ configMap := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "coredns-custom", Namespace: "gardener-extension-provider-local-coredns"}}
_, err := controllerutil.CreateOrPatch(ctx, a.Client, configMap, func() error {
mutate(configMap)
return nil
diff --git a/pkg/provider-local/controller/dnsrecord/actuator_test.go b/pkg/provider-local/controller/dnsrecord/actuator_test.go
index fb6edac999f..fe3d9303184 100644
--- a/pkg/provider-local/controller/dnsrecord/actuator_test.go
+++ b/pkg/provider-local/controller/dnsrecord/actuator_test.go
@@ -22,7 +22,6 @@ import (
"github.com/gardener/gardener/extensions/pkg/controller/dnsrecord"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
- "github.com/gardener/gardener/pkg/component/networking/coredns"
"github.com/gardener/gardener/pkg/logger"
. "github.com/gardener/gardener/pkg/provider-local/controller/dnsrecord"
)
@@ -104,14 +103,14 @@ var _ = Describe("Actuator", func() {
}
emptyConfigMap = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
- Name: coredns.CustomConfigMapName,
+ Name: "coredns-custom",
Namespace: extensionNamespace.Name,
},
Data: map[string]string{"test": "data"},
}
configMapWithRule = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
- Name: coredns.CustomConfigMapName,
+ Name: "coredns-custom",
Namespace: extensionNamespace.Name,
},
Data: map[string]string{
diff --git a/skaffold-gardenadm.yaml b/skaffold-gardenadm.yaml
index 63fecc64b89..fff45bdb73d 100644
--- a/skaffold-gardenadm.yaml
+++ b/skaffold-gardenadm.yaml
@@ -1132,8 +1132,6 @@ build:
- pkg/component/kubernetes/proxy
- pkg/component/kubernetes/proxy/resources/cleanup.sh
- pkg/component/kubernetes/proxy/resources/conntrack-fix.sh
- - pkg/component/networking/coredns
- - pkg/component/networking/coredns/constants
- pkg/component/nodemanagement/machinecontrollermanager
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml
diff --git a/skaffold-operator.yaml b/skaffold-operator.yaml
index 234857b7643..7f5dfe7f84f 100644
--- a/skaffold-operator.yaml
+++ b/skaffold-operator.yaml
@@ -1146,8 +1146,6 @@ build:
- pkg/component/kubernetes/proxy
- pkg/component/kubernetes/proxy/resources/cleanup.sh
- pkg/component/kubernetes/proxy/resources/conntrack-fix.sh
- - pkg/component/networking/coredns
- - pkg/component/networking/coredns/constants
- pkg/component/nodemanagement/machinecontrollermanager
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml
diff --git a/skaffold.yaml b/skaffold.yaml
index 1d8c51412d5..7bde9200a08 100644
--- a/skaffold.yaml
+++ b/skaffold.yaml
@@ -740,8 +740,6 @@ build:
- pkg/component/kubernetes/proxy
- pkg/component/kubernetes/proxy/resources/cleanup.sh
- pkg/component/kubernetes/proxy/resources/conntrack-fix.sh
- - pkg/component/networking/coredns
- - pkg/component/networking/coredns/constants
- pkg/component/nodemanagement/machinecontrollermanager
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml
From 27ae697aa03e1da3bde7041aecbe8c332e948e7f Mon Sep 17 00:00:00 2001
From: Sebastian Stauch
Date: Tue, 4 Nov 2025 17:36:18 +0100
Subject: [PATCH 030/176] Revert "If overlay gets disabled delay network
deployment until the control plane is fully operational (#13332)" (#13346)
This reverts commit 341416d59fc06977fcf0f69ea326b33bd114286b.
---
.../shoot/shoot/reconciler_reconcile.go | 71 +------------------
1 file changed, 1 insertion(+), 70 deletions(-)
diff --git a/pkg/gardenlet/controller/shoot/shoot/reconciler_reconcile.go b/pkg/gardenlet/controller/shoot/shoot/reconciler_reconcile.go
index 97eac950f3d..5e0afacff4c 100644
--- a/pkg/gardenlet/controller/shoot/shoot/reconciler_reconcile.go
+++ b/pkg/gardenlet/controller/shoot/shoot/reconciler_reconcile.go
@@ -6,14 +6,11 @@ package shoot
import (
"context"
- "encoding/json"
"fmt"
- "strconv"
"time"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -158,11 +155,6 @@ func (r *Reconciler) runReconcileShootFlow(ctx context.Context, o *operation.Ope
return v1beta1helper.NewWrappedLastErrors(v1beta1helper.FormatLastErrDescription(err), err)
}
- isOverlayDisablementInProgress, err := isOverlayDisablementInProgress(ctx, o.Shoot.GetInfo(), botanist.SeedClientSet.Client(), botanist.Shoot.ControlPlaneNamespace)
- if err != nil {
- return v1beta1helper.NewWrappedLastErrors(v1beta1helper.FormatLastErrDescription(err), err)
- }
-
var (
g = flow.NewGraph(fmt.Sprintf("Shoot cluster %s", utils.IifString(isRestoring, "restoration", "reconciliation")))
@@ -617,7 +609,7 @@ func (r *Reconciler) runReconcileShootFlow(ctx context.Context, o *operation.Ope
Name: "Deploying shoot network plugin",
Fn: flow.TaskFn(botanist.DeployNetwork).RetryUntilTimeout(defaultInterval, defaultTimeout),
SkipIf: o.Shoot.IsWorkerless,
- Dependencies: flow.NewTaskIDs(deployReferencedResources, waitUntilGardenerResourceManagerReady, waitUntilOperatingSystemConfigReady, deployKubeScheduler, waitUntilShootNamespacesReady).InsertIf(isOverlayDisablementInProgress, waitUntilControlPlaneReady),
+ Dependencies: flow.NewTaskIDs(deployReferencedResources, waitUntilGardenerResourceManagerReady, waitUntilOperatingSystemConfigReady, deployKubeScheduler, waitUntilShootNamespacesReady),
})
waitUntilNetworkIsReady = g.Add(flow.Task{
Name: "Waiting until shoot network plugin has been reconciled",
@@ -1090,64 +1082,3 @@ func shootHasPendingInPlaceUpdateWorkers(shoot *gardencorev1beta1.Shoot) bool {
return shoot.Status.InPlaceUpdates != nil && shoot.Status.InPlaceUpdates.PendingWorkerUpdates != nil &&
(len(shoot.Status.InPlaceUpdates.PendingWorkerUpdates.AutoInPlaceUpdate) > 0 || len(shoot.Status.InPlaceUpdates.PendingWorkerUpdates.ManualInPlaceUpdate) > 0)
}
-
-func isOverlayDisablementInProgress(ctx context.Context, shoot *gardencorev1beta1.Shoot, seedClient client.Client, shootControlPlaneNamespace string) (bool, error) {
- shootOverlayEnabled, err := getOverlayEnabledFromShootSpec(shoot)
- if err != nil {
- return false, fmt.Errorf("failed to get overlay enabled status from shoot spec: %w", err)
- }
-
- networkObj := &extensionsv1alpha1.Network{}
- if err = seedClient.Get(ctx, client.ObjectKey{Name: shoot.Name, Namespace: shootControlPlaneNamespace}, networkObj); err != nil {
- // If network doesn't exist yet, no switch in progress
- if apierrors.IsNotFound(err) {
- return false, nil
- }
-
- return false, fmt.Errorf("failed to get network object: %w", err)
- }
-
- networkOverlayEnabled, err := getOverlayEnabledFromProviderConfig(networkObj.Spec.ProviderConfig)
- if err != nil {
- return false, fmt.Errorf("failed to get overlay enabled status from provider config: %w", err)
- }
-
- // If settings differ, overlay switch is in progress - need to wait for control plane
- return !shootOverlayEnabled && networkOverlayEnabled, nil
-}
-
-func getOverlayEnabledFromShootSpec(shoot *gardencorev1beta1.Shoot) (bool, error) {
- if shoot.Spec.Networking == nil || shoot.Spec.Networking.ProviderConfig == nil {
- return true, nil
- }
-
- return getOverlayEnabledFromProviderConfig(shoot.Spec.Networking.ProviderConfig)
-}
-
-func getOverlayEnabledFromProviderConfig(providerConfig *runtime.RawExtension) (bool, error) {
- if providerConfig == nil {
- return true, nil
- }
-
- var config map[string]interface{}
- if err := json.Unmarshal(providerConfig.Raw, &config); err != nil {
- return false, fmt.Errorf("failed to unmarshal provider config: %w", err)
- }
-
- if overlay, exists := config["overlay"]; exists {
- if overlayMap, ok := overlay.(map[string]interface{}); ok {
- if enabled, exists := overlayMap["enabled"]; exists {
- if enabledStr, ok := enabled.(string); ok {
- enabledBool, err := strconv.ParseBool(enabledStr)
- if err != nil {
- return false, fmt.Errorf("failed to get overlay enabled status from provider config: %w", err)
- }
-
- return enabledBool, nil
- }
- }
- }
- }
-
- return true, nil
-}
From 56564deef7903feb9c927d46b62140abb4369655 Mon Sep 17 00:00:00 2001
From: Axel Siebenborn
Date: Tue, 4 Nov 2025 22:09:06 +0100
Subject: [PATCH 031/176] Generate an ULA as services range for workerless IPv6
shoots. (#13224)
---
plugin/pkg/shoot/mutator/admission.go | 66 ++++++++++++++++----
plugin/pkg/shoot/mutator/admission_test.go | 40 +++++++++++-
plugin/pkg/shoot/validator/admission.go | 7 ++-
plugin/pkg/shoot/validator/admission_test.go | 35 +++++++++++
4 files changed, 133 insertions(+), 15 deletions(-)
diff --git a/plugin/pkg/shoot/mutator/admission.go b/plugin/pkg/shoot/mutator/admission.go
index db3e660ebe7..db7cd9a89df 100644
--- a/plugin/pkg/shoot/mutator/admission.go
+++ b/plugin/pkg/shoot/mutator/admission.go
@@ -6,6 +6,7 @@ package mutator
import (
"context"
+ "crypto/rand"
"errors"
"fmt"
"io"
@@ -229,18 +230,44 @@ func addDeploymentTasks(shoot *core.Shoot, tasks ...string) {
}
func (c *mutationContext) defaultShootNetworks(workerless bool) {
- if c.seed != nil {
- if c.shoot.Spec.Networking.Pods == nil && !workerless &&
- c.seed.Spec.Networks.ShootDefaults != nil && c.seed.Spec.Networks.ShootDefaults.Pods != nil &&
- cidrMatchesIPFamily(*c.seed.Spec.Networks.ShootDefaults.Pods, c.shoot.Spec.Networking.IPFamilies) {
- c.shoot.Spec.Networking.Pods = c.seed.Spec.Networks.ShootDefaults.Pods
- }
+ if c.seed == nil {
+ return
+ }
- if c.shoot.Spec.Networking.Services == nil &&
- c.seed.Spec.Networks.ShootDefaults != nil && c.seed.Spec.Networks.ShootDefaults.Services != nil &&
- cidrMatchesIPFamily(*c.seed.Spec.Networks.ShootDefaults.Services, c.shoot.Spec.Networking.IPFamilies) {
- c.shoot.Spec.Networking.Services = c.seed.Spec.Networks.ShootDefaults.Services
- }
+ c.defaultPodsNetwork(workerless)
+ c.defaultServicesNetwork(workerless)
+}
+
+func (c *mutationContext) defaultPodsNetwork(workerless bool) {
+ if c.shoot.Spec.Networking.Pods != nil || workerless {
+ return
+ }
+
+ defaults := c.seed.Spec.Networks.ShootDefaults
+ if defaults == nil || defaults.Pods == nil {
+ return
+ }
+
+ if cidrMatchesIPFamily(*defaults.Pods, c.shoot.Spec.Networking.IPFamilies) {
+ c.shoot.Spec.Networking.Pods = defaults.Pods
+ }
+}
+
+func (c *mutationContext) defaultServicesNetwork(workerless bool) {
+ if c.shoot.Spec.Networking.Services != nil {
+ return
+ }
+
+ defaults := c.seed.Spec.Networks.ShootDefaults
+ if defaults != nil && defaults.Services != nil &&
+ cidrMatchesIPFamily(*defaults.Services, c.shoot.Spec.Networking.IPFamilies) {
+ c.shoot.Spec.Networking.Services = defaults.Services
+ return
+ }
+
+ if workerless && slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv6) {
+ ulaCIDR := generateULAServicesCIDR()
+ c.shoot.Spec.Networking.Services = &ulaCIDR
}
}
@@ -248,3 +275,20 @@ func cidrMatchesIPFamily(cidr string, ipfamilies []core.IPFamily) bool {
ip, _, _ := net.ParseCIDR(cidr)
return ip != nil && (ip.To4() != nil && slices.Contains(ipfamilies, core.IPFamilyIPv4) || ip.To4() == nil && slices.Contains(ipfamilies, core.IPFamilyIPv6))
}
+
+// generateULAServicesCIDR generates a /112 ULA (Unique Local Address) CIDR for IPv6 services.
+func generateULAServicesCIDR() string {
+ // Generate a random 40-bit Global ID (5 bytes) for the ULA
+ // ULA format: fd + 40-bit Global ID + 16-bit Subnet-ID + 64-bit Interface ID
+ // For services, we use a /112 which leaves 16 bits for service IPs
+
+ var globalID [5]byte
+ if _, err := rand.Read(globalID[:]); err != nil {
+ // Fallback to a deterministic value if random generation fails
+ return "fd00:10:2::/112"
+ }
+
+ // Format as fd + 5 bytes of Global ID + 2 bytes of Subnet ID (using 0000 for services)
+ return fmt.Sprintf("fd%02x:%02x%02x:%02x%02x::/112",
+ globalID[0], globalID[1], globalID[2], globalID[3], globalID[4])
+}
diff --git a/plugin/pkg/shoot/mutator/admission_test.go b/plugin/pkg/shoot/mutator/admission_test.go
index d99d88e1513..a62389db0b7 100644
--- a/plugin/pkg/shoot/mutator/admission_test.go
+++ b/plugin/pkg/shoot/mutator/admission_test.go
@@ -6,6 +6,7 @@ package mutator_test
import (
"context"
+ "net"
"time"
. "github.com/onsi/ginkgo/v2"
@@ -422,7 +423,7 @@ var _ = Describe("mutator", func() {
Expect(shoot.Spec.Networking.Services).To(BeNil())
})
- It("should not default shoot pod network if shoot is workerless", func() {
+ It("should skip pod network defaulting but default service network for workerless shoots", func() {
shoot.Spec.Provider.Workers = nil
Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
@@ -435,6 +436,43 @@ var _ = Describe("mutator", func() {
Expect(shoot.Spec.Networking.Services).To(Equal(&servicesCIDR))
})
+ It("should generate ULA services CIDR for workerless IPv6 shoots without seed defaults", func() {
+ shoot.Spec.Provider.Workers = nil
+ shoot.Spec.Networking.IPFamilies = []core.IPFamily{core.IPFamilyIPv6}
+ Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).NotTo(HaveOccurred())
+ Expect(shoot.Spec.Networking.Pods).To(BeNil())
+
+ Expect(shoot.Spec.Networking.Services).NotTo(BeNil())
+ servicesCIDR := *shoot.Spec.Networking.Services
+ _, ipNet, parseErr := net.ParseCIDR(servicesCIDR)
+ Expect(parseErr).NotTo(HaveOccurred(), "Generated services CIDR should be valid")
+ Expect(ipNet.IP.To16()).NotTo(BeNil(), "Generated services CIDR should be IPv6")
+ Expect(ipNet.IP[0]).To(Equal(byte(0xfd)), "Generated services CIDR should be in ULA range (fd00::/8)")
+ Expect(shoot.Spec.Networking.Services).To(Equal(&servicesCIDR))
+ })
+
+ It("should use seed defaults for workerless IPv6 shoots when available", func() {
+ servicesCIDR := "2001:db8:10::/112"
+ seed.Spec.Networks.ShootDefaults.Services = ptr.To(servicesCIDR)
+ shoot.Spec.Provider.Workers = nil
+ shoot.Spec.Networking.IPFamilies = []core.IPFamily{core.IPFamilyIPv6}
+ Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).NotTo(HaveOccurred())
+ Expect(shoot.Spec.Networking.Pods).To(BeNil())
+
+ Expect(shoot.Spec.Networking.Services).NotTo(BeNil())
+ Expect(shoot.Spec.Networking.Services).To(Equal(&servicesCIDR))
+ })
+
It("should not default shoot networks if shoot IP family does not match seed .spec.networks.shootDefaults", func() {
shoot.Spec.Networking.IPFamilies = []core.IPFamily{core.IPFamilyIPv6}
diff --git a/plugin/pkg/shoot/validator/admission.go b/plugin/pkg/shoot/validator/admission.go
index 7bd770a22da..c35b0f309df 100644
--- a/plugin/pkg/shoot/validator/admission.go
+++ b/plugin/pkg/shoot/validator/admission.go
@@ -874,9 +874,10 @@ func (c *validationContext) validateShootNetworks(a admission.Attributes, worker
allErrs = append(allErrs, field.Required(path.Child("pods"), "pods is required"))
}
- if c.shoot.Spec.Networking.Services == nil &&
- slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv4) {
- allErrs = append(allErrs, field.Required(path.Child("services"), "services is required"))
+ if c.shoot.Spec.Networking.Services == nil {
+ if slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv4) || (workerless && slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv6)) {
+ allErrs = append(allErrs, field.Required(path.Child("services"), "services is required"))
+ }
}
if slices.Contains(c.shoot.Spec.Networking.IPFamilies, core.IPFamilyIPv4) {
diff --git a/plugin/pkg/shoot/validator/admission_test.go b/plugin/pkg/shoot/validator/admission_test.go
index 92975828121..01b6eea6a2a 100644
--- a/plugin/pkg/shoot/validator/admission_test.go
+++ b/plugin/pkg/shoot/validator/admission_test.go
@@ -2322,6 +2322,41 @@ var _ = Describe("validator", func() {
})
+ It("should reject because shoot services network is nil (workerless Shoot, Ipv6)", func() {
+ shoot.Spec.Provider.Workers = nil
+ shoot.Spec.Networking.Services = nil
+ shoot.Spec.Networking.IPFamilies = []core.IPFamily{core.IPFamilyIPv6}
+
+ Expect(coreInformerFactory.Core().V1beta1().Projects().Informer().GetStore().Add(&project)).To(Succeed())
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(&cloudProfile)).To(Succeed())
+ Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
+ Expect(coreInformerFactory.Core().V1beta1().SecretBindings().Informer().GetStore().Add(&secretBinding)).To(Succeed())
+ Expect(securityInformerFactory.Security().V1alpha1().CredentialsBindings().Informer().GetStore().Add(&credentialsBinding)).To(Succeed())
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).To(HaveOccurred())
+ Expect(err).To(MatchError(ContainSubstring("services is required")))
+
+ })
+
+ It("should not reject because shoot services network is nil for IPv6", func() {
+ shoot.Spec.Networking.Services = nil
+ shoot.Spec.Networking.IPFamilies = []core.IPFamily{core.IPFamilyIPv6}
+
+ Expect(coreInformerFactory.Core().V1beta1().Projects().Informer().GetStore().Add(&project)).To(Succeed())
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(&cloudProfile)).To(Succeed())
+ Expect(coreInformerFactory.Core().V1beta1().Seeds().Informer().GetStore().Add(&seed)).To(Succeed())
+ Expect(coreInformerFactory.Core().V1beta1().SecretBindings().Informer().GetStore().Add(&secretBinding)).To(Succeed())
+ Expect(securityInformerFactory.Security().V1alpha1().CredentialsBindings().Informer().GetStore().Add(&credentialsBinding)).To(Succeed())
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).NotTo(HaveOccurred())
+ })
+
It("should reject because the shoot node and the seed node networks intersect (HA control plane)", func() {
shoot.Spec.Networking.Nodes = &seedNodesCIDR
shoot.Spec.ControlPlane = &core.ControlPlane{HighAvailability: &core.HighAvailability{FailureTolerance: core.FailureTolerance{Type: core.FailureToleranceTypeZone}}}
From c0fe68f8b19b94895fe7016f05f6f09efa4e37c3 Mon Sep 17 00:00:00 2001
From: Ismail Alidzhikov <9372594+ialidzhikov@users.noreply.github.com>
Date: Wed, 5 Nov 2025 09:53:17 +0200
Subject: [PATCH 032/176] Fetch the referenced `CloudProfile` /
`NamespacedCloudProfile` (part 4) (#13222)
* Fetch the referenced CloudProfile / NamespacedCloudProfile
* Fix integration tests
---
plugin/pkg/shoot/mutator/admission.go | 44 ++++++++++++++----
plugin/pkg/shoot/mutator/admission_test.go | 46 +++++++++++++++++--
.../seed/seed_suite_test.go | 2 +-
.../credentialsbinding_suite_test.go | 2 +-
.../exposureclass/exposureclass_suite_test.go | 2 +-
.../managedseedset_suite_test.go | 2 +-
.../project/activity/activity_suite_test.go | 2 +-
.../project/project/project_suite_test.go | 2 +-
.../project/stale/stale_suite_test.go | 2 +-
.../secretbinding/secretbinding_suite_test.go | 2 +-
.../seed/lifecycle/lifecycle_suite_test.go | 2 +-
.../shoot/conditions/conditions_suite_test.go | 2 +-
.../hibernation/hibernation_suite_test.go | 2 +-
.../maintenance/maintenance_suite_test.go | 2 +-
.../shoot/quota/quota_suite_test.go | 2 +-
.../shoot/reference/reference_suite_test.go | 2 +-
.../shoot/retry/retry_suite_test.go | 2 +-
.../statuslabel/statuslabel_suite_test.go | 2 +-
.../backupentry/backupentry_suite_test.go | 2 +-
.../gardenlet/bastion/bastion_suite_test.go | 2 +-
.../managedseed/managedseed_suite_test.go | 2 +-
.../gardenlet/shoot/care/care_suite_test.go | 2 +-
22 files changed, 96 insertions(+), 34 deletions(-)
diff --git a/plugin/pkg/shoot/mutator/admission.go b/plugin/pkg/shoot/mutator/admission.go
index db7cd9a89df..33cefdda30b 100644
--- a/plugin/pkg/shoot/mutator/admission.go
+++ b/plugin/pkg/shoot/mutator/admission.go
@@ -29,6 +29,7 @@ import (
gardencoreinformers "github.com/gardener/gardener/pkg/client/core/informers/externalversions"
gardencorev1beta1listers "github.com/gardener/gardener/pkg/client/core/listers/core/v1beta1"
"github.com/gardener/gardener/pkg/controllerutils"
+ gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
plugin "github.com/gardener/gardener/plugin/pkg"
)
@@ -43,8 +44,10 @@ func Register(plugins *admission.Plugins) {
type MutateShoot struct {
*admission.Handler
- seedLister gardencorev1beta1listers.SeedLister
- readyFunc admission.ReadyFunc
+ cloudProfileLister gardencorev1beta1listers.CloudProfileLister
+ namespacedCloudProfileLister gardencorev1beta1listers.NamespacedCloudProfileLister
+ seedLister gardencorev1beta1listers.SeedLister
+ readyFunc admission.ReadyFunc
}
var (
@@ -68,17 +71,31 @@ func (m *MutateShoot) AssignReadyFunc(f admission.ReadyFunc) {
// SetCoreInformerFactory gets Lister from SharedInformerFactory.
func (m *MutateShoot) SetCoreInformerFactory(f gardencoreinformers.SharedInformerFactory) {
+ cloudProfileInformer := f.Core().V1beta1().CloudProfiles()
+ m.cloudProfileLister = cloudProfileInformer.Lister()
+
+ namespacedCloudProfileInformer := f.Core().V1beta1().NamespacedCloudProfiles()
+ m.namespacedCloudProfileLister = namespacedCloudProfileInformer.Lister()
+
seedInformer := f.Core().V1beta1().Seeds()
m.seedLister = seedInformer.Lister()
readyFuncs = append(
readyFuncs,
+ cloudProfileInformer.Informer().HasSynced,
+ namespacedCloudProfileInformer.Informer().HasSynced,
seedInformer.Informer().HasSynced,
)
}
// ValidateInitialization checks whether the plugin was correctly initialized.
func (m *MutateShoot) ValidateInitialization() error {
+ if m.cloudProfileLister == nil {
+ return errors.New("missing cloudProfile lister")
+ }
+ if m.namespacedCloudProfileLister == nil {
+ return errors.New("missing namespacedCloudProfile lister")
+ }
if m.seedLister == nil {
return errors.New("missing seed lister")
}
@@ -126,9 +143,16 @@ func (m *MutateShoot) Admit(_ context.Context, a admission.Attributes, _ admissi
}
}
+ cloudProfileSpec, err := gardenerutils.GetCloudProfileSpec(m.cloudProfileLister, m.namespacedCloudProfileLister, shoot)
+ if err != nil {
+ return apierrors.NewInternalError(fmt.Errorf("could not find referenced cloud profile: %w", err))
+ }
+ if cloudProfileSpec == nil {
+ return nil
+ }
+
var seed *gardencorev1beta1.Seed
if shoot.Spec.SeedName != nil {
- var err error
seed, err = m.seedLister.Get(*shoot.Spec.SeedName)
if err != nil {
return apierrors.NewInternalError(fmt.Errorf("could not find referenced seed %q: %w", *shoot.Spec.SeedName, err))
@@ -136,9 +160,10 @@ func (m *MutateShoot) Admit(_ context.Context, a admission.Attributes, _ admissi
}
mutationContext := &mutationContext{
- seed: seed,
- shoot: shoot,
- oldShoot: oldShoot,
+ cloudProfileSpec: cloudProfileSpec,
+ seed: seed,
+ shoot: shoot,
+ oldShoot: oldShoot,
}
if a.GetOperation() == admission.Create {
@@ -152,9 +177,10 @@ func (m *MutateShoot) Admit(_ context.Context, a admission.Attributes, _ admissi
}
type mutationContext struct {
- seed *gardencorev1beta1.Seed
- shoot *core.Shoot
- oldShoot *core.Shoot
+ cloudProfileSpec *gardencorev1beta1.CloudProfileSpec
+ seed *gardencorev1beta1.Seed
+ shoot *core.Shoot
+ oldShoot *core.Shoot
}
func addCreatedByAnnotation(shoot *core.Shoot, userName string) {
diff --git a/plugin/pkg/shoot/mutator/admission_test.go b/plugin/pkg/shoot/mutator/admission_test.go
index a62389db0b7..95377e51a8a 100644
--- a/plugin/pkg/shoot/mutator/admission_test.go
+++ b/plugin/pkg/shoot/mutator/admission_test.go
@@ -51,12 +51,12 @@ var _ = Describe("mutator", func() {
})
Describe("#ValidateInitialization", func() {
- It("should return error if no SeedLister is set", func() {
+ It("should return error if a lister is missing", func() {
admissionHandler, err := New()
Expect(err).NotTo(HaveOccurred())
err = admissionHandler.ValidateInitialization()
- Expect(err).To(MatchError("missing seed lister"))
+ Expect(err).To(MatchError("missing cloudProfile lister"))
})
It("should not return error if all listers are set", func() {
@@ -73,9 +73,10 @@ var _ = Describe("mutator", func() {
var (
ctx context.Context
- userInfo = &user.DefaultInfo{Name: "foo"}
- seed gardencorev1beta1.Seed
- shoot core.Shoot
+ userInfo = &user.DefaultInfo{Name: "foo"}
+ cloudProfile gardencorev1beta1.CloudProfile
+ seed gardencorev1beta1.Seed
+ shoot core.Shoot
coreInformerFactory gardencoreinformers.SharedInformerFactory
@@ -85,6 +86,11 @@ var _ = Describe("mutator", func() {
BeforeEach(func() {
ctx = context.Background()
+ cloudProfile = gardencorev1beta1.CloudProfile{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "profile",
+ },
+ }
seed = gardencorev1beta1.Seed{
ObjectMeta: metav1.ObjectMeta{
Name: "seed",
@@ -96,6 +102,7 @@ var _ = Describe("mutator", func() {
Namespace: "garden-my-project",
},
Spec: core.ShootSpec{
+ CloudProfileName: ptr.To("profile"),
Provider: core.Provider{
Workers: []core.Worker{
{
@@ -152,7 +159,26 @@ var _ = Describe("mutator", func() {
})
Context("reference checks", func() {
+ It("should reject because the referenced cloud profile was not found", func() {
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+ err := admissionHandler.Admit(ctx, attrs, nil)
+
+ Expect(err).To(BeInternalServerError())
+ })
+
+ It("should exit early if CloudProfile is not set", func() {
+ shoot.Spec.CloudProfileName = nil
+ shoot.Spec.CloudProfile = nil
+
+ attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
+
+ err := admissionHandler.Admit(ctx, attrs, nil)
+ Expect(err).NotTo(HaveOccurred())
+ })
+
It("should reject because the referenced seed was not found", func() {
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(&cloudProfile)).To(Succeed())
+
shoot.Spec.SeedName = ptr.To("seed")
attrs := admission.NewAttributesRecord(&shoot, nil, core.Kind("Shoot").WithVersion("version"), shoot.Namespace, shoot.Name, core.Resource("shoots").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, userInfo)
@@ -162,6 +188,10 @@ var _ = Describe("mutator", func() {
})
Context("created-by annotation", func() {
+ BeforeEach(func() {
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(&cloudProfile)).To(Succeed())
+ })
+
It("should add the created-by annotation on shoot creation", func() {
Expect(shoot.Annotations).NotTo(HaveKeyWithValue(v1beta1constants.GardenCreatedBy, userInfo.Name))
@@ -189,6 +219,8 @@ var _ = Describe("mutator", func() {
BeforeEach(func() {
oldShoot = shoot.DeepCopy()
+
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(&cloudProfile)).To(Succeed())
})
It("should add deploy tasks because shoot is being created", func() {
@@ -333,6 +365,8 @@ var _ = Describe("mutator", func() {
BeforeEach(func() {
shoot.Spec.Maintenance = &core.Maintenance{}
oldShoot = shoot.DeepCopy()
+
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(&cloudProfile)).To(Succeed())
})
DescribeTable("confine spec roll-out checks",
@@ -397,6 +431,8 @@ var _ = Describe("mutator", func() {
Services: nil,
IPFamilies: []core.IPFamily{core.IPFamilyIPv4},
}
+
+ Expect(coreInformerFactory.Core().V1beta1().CloudProfiles().Informer().GetStore().Add(&cloudProfile)).To(Succeed())
})
It("should not default shoot networks if shoot .spec.seedName is nil", func() {
diff --git a/test/integration/controllermanager/controllerregistration/seed/seed_suite_test.go b/test/integration/controllermanager/controllerregistration/seed/seed_suite_test.go
index 3d81fb9c500..8f054463d49 100644
--- a/test/integration/controllermanager/controllerregistration/seed/seed_suite_test.go
+++ b/test/integration/controllermanager/controllerregistration/seed/seed_suite_test.go
@@ -74,7 +74,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ControllerRegistrationResources"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ControllerRegistrationResources,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/credentialsbinding/credentialsbinding_suite_test.go b/test/integration/controllermanager/credentialsbinding/credentialsbinding_suite_test.go
index cff25bce225..ac14e0ddf51 100644
--- a/test/integration/controllermanager/credentialsbinding/credentialsbinding_suite_test.go
+++ b/test/integration/controllermanager/credentialsbinding/credentialsbinding_suite_test.go
@@ -59,7 +59,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/exposureclass/exposureclass_suite_test.go b/test/integration/controllermanager/exposureclass/exposureclass_suite_test.go
index e156cad9b3b..7779ef9cf10 100644
--- a/test/integration/controllermanager/exposureclass/exposureclass_suite_test.go
+++ b/test/integration/controllermanager/exposureclass/exposureclass_suite_test.go
@@ -64,7 +64,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootExposureClass,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootExposureClass,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/managedseedset/managedseedset_suite_test.go b/test/integration/controllermanager/managedseedset/managedseedset_suite_test.go
index f3faecdb2aa..284840261e6 100644
--- a/test/integration/controllermanager/managedseedset/managedseedset_suite_test.go
+++ b/test/integration/controllermanager/managedseedset/managedseedset_suite_test.go
@@ -62,7 +62,7 @@ var _ = BeforeSuite(func() {
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
Args: []string{
- "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,SeedValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootValidator",
+ "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,SeedValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootValidator,ShootMutator",
},
},
}
diff --git a/test/integration/controllermanager/project/activity/activity_suite_test.go b/test/integration/controllermanager/project/activity/activity_suite_test.go
index 3c0d052eb83..d27a014a293 100644
--- a/test/integration/controllermanager/project/activity/activity_suite_test.go
+++ b/test/integration/controllermanager/project/activity/activity_suite_test.go
@@ -61,7 +61,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ExtensionLabels,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ExtensionLabels,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/project/project/project_suite_test.go b/test/integration/controllermanager/project/project/project_suite_test.go
index 23114840f17..3a26cebeddc 100644
--- a/test/integration/controllermanager/project/project/project_suite_test.go
+++ b/test/integration/controllermanager/project/project/project_suite_test.go
@@ -69,7 +69,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/project/stale/stale_suite_test.go b/test/integration/controllermanager/project/stale/stale_suite_test.go
index 7ac03cfb3fd..1b604f6c01b 100644
--- a/test/integration/controllermanager/project/stale/stale_suite_test.go
+++ b/test/integration/controllermanager/project/stale/stale_suite_test.go
@@ -69,7 +69,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ExtensionLabels,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ExtensionLabels,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/secretbinding/secretbinding_suite_test.go b/test/integration/controllermanager/secretbinding/secretbinding_suite_test.go
index a4537a38a66..c967a14cfdb 100644
--- a/test/integration/controllermanager/secretbinding/secretbinding_suite_test.go
+++ b/test/integration/controllermanager/secretbinding/secretbinding_suite_test.go
@@ -59,7 +59,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/seed/lifecycle/lifecycle_suite_test.go b/test/integration/controllermanager/seed/lifecycle/lifecycle_suite_test.go
index 44abd21ecb0..f354fbdfde2 100644
--- a/test/integration/controllermanager/seed/lifecycle/lifecycle_suite_test.go
+++ b/test/integration/controllermanager/seed/lifecycle/lifecycle_suite_test.go
@@ -69,7 +69,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,SeedValidator,SeedMutator,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,SeedValidator,SeedMutator,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/shoot/conditions/conditions_suite_test.go b/test/integration/controllermanager/shoot/conditions/conditions_suite_test.go
index 55aef39fc5e..da0e3fef7bd 100644
--- a/test/integration/controllermanager/shoot/conditions/conditions_suite_test.go
+++ b/test/integration/controllermanager/shoot/conditions/conditions_suite_test.go
@@ -59,7 +59,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/shoot/hibernation/hibernation_suite_test.go b/test/integration/controllermanager/shoot/hibernation/hibernation_suite_test.go
index fd1de2fd55e..b69dacfd989 100644
--- a/test/integration/controllermanager/shoot/hibernation/hibernation_suite_test.go
+++ b/test/integration/controllermanager/shoot/hibernation/hibernation_suite_test.go
@@ -59,7 +59,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/shoot/maintenance/maintenance_suite_test.go b/test/integration/controllermanager/shoot/maintenance/maintenance_suite_test.go
index f603ef6680f..ae49aa7e44d 100644
--- a/test/integration/controllermanager/shoot/maintenance/maintenance_suite_test.go
+++ b/test/integration/controllermanager/shoot/maintenance/maintenance_suite_test.go
@@ -63,7 +63,7 @@ var _ = BeforeSuite(func() {
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
Args: []string{
- "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction",
+ "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootMutator",
},
},
}
diff --git a/test/integration/controllermanager/shoot/quota/quota_suite_test.go b/test/integration/controllermanager/shoot/quota/quota_suite_test.go
index a0b6aabf2e7..5d5d13e78ba 100644
--- a/test/integration/controllermanager/shoot/quota/quota_suite_test.go
+++ b/test/integration/controllermanager/shoot/quota/quota_suite_test.go
@@ -62,7 +62,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/shoot/reference/reference_suite_test.go b/test/integration/controllermanager/shoot/reference/reference_suite_test.go
index a94add97447..b675e1446ab 100644
--- a/test/integration/controllermanager/shoot/reference/reference_suite_test.go
+++ b/test/integration/controllermanager/shoot/reference/reference_suite_test.go
@@ -57,7 +57,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/shoot/retry/retry_suite_test.go b/test/integration/controllermanager/shoot/retry/retry_suite_test.go
index 22cd7e1b00c..66b4f442683 100644
--- a/test/integration/controllermanager/shoot/retry/retry_suite_test.go
+++ b/test/integration/controllermanager/shoot/retry/retry_suite_test.go
@@ -57,7 +57,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootMutator"},
},
}
diff --git a/test/integration/controllermanager/shoot/statuslabel/statuslabel_suite_test.go b/test/integration/controllermanager/shoot/statuslabel/statuslabel_suite_test.go
index ca48d66d728..3ebc629fdbb 100644
--- a/test/integration/controllermanager/shoot/statuslabel/statuslabel_suite_test.go
+++ b/test/integration/controllermanager/shoot/statuslabel/statuslabel_suite_test.go
@@ -57,7 +57,7 @@ var _ = BeforeSuite(func() {
By("Start test environment")
testEnv = &gardenerenvtest.GardenerTestEnvironment{
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootQuotaValidator,ShootValidator,ShootTolerationRestriction,ShootDNS,ShootMutator"},
},
}
diff --git a/test/integration/gardenlet/backupentry/backupentry_suite_test.go b/test/integration/gardenlet/backupentry/backupentry_suite_test.go
index c2baa2a2354..af8996181d7 100644
--- a/test/integration/gardenlet/backupentry/backupentry_suite_test.go
+++ b/test/integration/gardenlet/backupentry/backupentry_suite_test.go
@@ -87,7 +87,7 @@ var _ = BeforeSuite(func() {
ErrorIfCRDPathMissing: true,
},
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,Bastion,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,Bastion,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ShootMutator"},
},
}
diff --git a/test/integration/gardenlet/bastion/bastion_suite_test.go b/test/integration/gardenlet/bastion/bastion_suite_test.go
index c83bd80a6ef..fc4521385c3 100644
--- a/test/integration/gardenlet/bastion/bastion_suite_test.go
+++ b/test/integration/gardenlet/bastion/bastion_suite_test.go
@@ -87,7 +87,7 @@ var _ = BeforeSuite(func() {
ErrorIfCRDPathMissing: true,
},
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,Bastion,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,SeedValidator"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,Bastion,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,SeedValidator,ShootMutator"},
},
}
diff --git a/test/integration/gardenlet/managedseed/managedseed_suite_test.go b/test/integration/gardenlet/managedseed/managedseed_suite_test.go
index c30b33b6841..375395233cf 100644
--- a/test/integration/gardenlet/managedseed/managedseed_suite_test.go
+++ b/test/integration/gardenlet/managedseed/managedseed_suite_test.go
@@ -84,7 +84,7 @@ var _ = BeforeSuite(func() {
Environment: &envtest.Environment{},
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
Args: []string{
- "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,SeedValidator,ShootQuotaValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootDNS,ShootValidator,SeedValidator",
+ "--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,SeedValidator,ShootQuotaValidator,ShootTolerationRestriction,ManagedSeedShoot,ManagedSeed,ShootManagedSeed,ShootDNS,ShootValidator,SeedValidator,ShootMutator",
},
},
}
diff --git a/test/integration/gardenlet/shoot/care/care_suite_test.go b/test/integration/gardenlet/shoot/care/care_suite_test.go
index a92c6e65ea6..cd2228a4202 100644
--- a/test/integration/gardenlet/shoot/care/care_suite_test.go
+++ b/test/integration/gardenlet/shoot/care/care_suite_test.go
@@ -118,7 +118,7 @@ var _ = BeforeSuite(func() {
ErrorIfCRDPathMissing: true,
},
GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
- Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator"},
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ShootMutator"},
},
}
From 50281d280afc360c0d55f4cac632a0bbfccf4994 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Wed, 5 Nov 2025 10:52:17 +0100
Subject: [PATCH 033/176] Update quay.io/prometheus/node-exporter Docker tag to
v1.10.2 (#13266)
---
imagevector/containers.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index 585af4b3f6a..a58dc41993f 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -317,7 +317,7 @@ images:
- name: node-exporter
sourceRepository: github.com/prometheus/node_exporter
repository: quay.io/prometheus/node-exporter
- tag: v1.9.1
+ tag: v1.10.2
labels:
- name: gardener.cloud/cve-categorisation
value:
From ab10b0ae988a42ab9e4e5c5c62b2e932d107ff00 Mon Sep 17 00:00:00 2001
From: Vladimir Nachev
Date: Wed, 5 Nov 2025 11:52:24 +0200
Subject: [PATCH 034/176] [GEP-26] Fix backup migration from WorkloadIdentity
to Secret (#13282)
* Fix backup migration from WorkloadIdentity to Secret
When the WorkloadIdentity relevant annotations and labels are left on
the backup bucket/entry secret in the seed, other controllers decides
that indeed WorkloadIdentity credentials are being used, however they
fail to reconcile because data fields like 'config' are not set.
Therefore, the backupbucket and backupentry controllers now cleanup all
unknown annotations and labels. Data fields are already being cleaned up.
* Change backupentry genericactuator to unset the annotations and labels
---
.../backupentry/genericactuator/actuator.go | 4 ++++
.../genericactuator/actuator_test.go | 19 +++++++++++++++++++
.../controller/backupbucket/reconciler.go | 3 ++-
.../backupbucket/reconciler_test.go | 16 ++++++++++++++++
.../controller/backupentry/reconciler.go | 3 ++-
.../controller/backupentry/reconciler_test.go | 17 +++++++++++++++++
6 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/extensions/pkg/controller/backupentry/genericactuator/actuator.go b/extensions/pkg/controller/backupentry/genericactuator/actuator.go
index e743b25ff82..afef0369e15 100644
--- a/extensions/pkg/controller/backupentry/genericactuator/actuator.go
+++ b/extensions/pkg/controller/backupentry/genericactuator/actuator.go
@@ -132,6 +132,10 @@ func (a *actuator) deployEtcdBackupSecret(ctx context.Context, log logr.Logger,
if token, ok := etcdSecret.Data[securityv1alpha1constants.DataKeyToken]; ok {
etcdSecretData[securityv1alpha1constants.DataKeyToken] = token
}
+ } else {
+ // Unset all annotations and labels when static credentials are used.
+ etcdSecret.Annotations = map[string]string{}
+ etcdSecret.Labels = nil
}
metav1.SetMetaDataAnnotation(&etcdSecret.ObjectMeta, AnnotationKeyCreatedByBackupEntry, be.Name)
diff --git a/extensions/pkg/controller/backupentry/genericactuator/actuator_test.go b/extensions/pkg/controller/backupentry/genericactuator/actuator_test.go
index d5eb8c584f3..0823728f456 100644
--- a/extensions/pkg/controller/backupentry/genericactuator/actuator_test.go
+++ b/extensions/pkg/controller/backupentry/genericactuator/actuator_test.go
@@ -153,6 +153,25 @@ var _ = Describe("Actuator", func() {
Expect(actual.Data).To(Equal(etcdBackupSecretData))
})
+ It("should remove all unknown annotations and labels from the etcd-backup secret", func() {
+ existingEtcdBackupSecret := etcdBackupSecret.DeepCopy()
+ testKeyValue := map[string]string{"key1": "value1", "key2:": "value2"}
+ existingEtcdBackupSecret.Annotations = testKeyValue
+ existingEtcdBackupSecret.Labels = testKeyValue
+
+ fakeClient = fakeclient.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(seedNamespace, backupEntrySecret, existingEtcdBackupSecret).Build()
+ mgr.EXPECT().GetClient().Return(fakeClient)
+ backupEntryDelegate.EXPECT().GetETCDSecretData(ctx, gomock.AssignableToTypeOf(logr.Logger{}), backupEntry, backupProviderSecretData).Return(etcdBackupSecretData, nil)
+
+ a = genericactuator.NewActuator(mgr, backupEntryDelegate)
+ Expect(a.Reconcile(ctx, log, backupEntry)).To(Succeed())
+
+ actual := &corev1.Secret{}
+ Expect(fakeClient.Get(ctx, etcdBackupSecretKey, actual)).To(Succeed())
+ Expect(actual.Annotations).To(Equal(map[string]string{"backup.gardener.cloud/created-by": backupEntry.Name}))
+ Expect(actual.Labels).To(BeEmpty())
+ })
+
Context("#WorkloadIdentity", func() {
var existingEtcdBackupSecret *corev1.Secret
diff --git a/pkg/gardenlet/controller/backupbucket/reconciler.go b/pkg/gardenlet/controller/backupbucket/reconciler.go
index 2c1c0ca2d97..cdf508ffff4 100644
--- a/pkg/gardenlet/controller/backupbucket/reconciler.go
+++ b/pkg/gardenlet/controller/backupbucket/reconciler.go
@@ -374,7 +374,8 @@ func (r *Reconciler) reconcileBackupBucketExtensionSecret(ctx context.Context, e
switch credentials := backupCredentials.(type) {
case *corev1.Secret:
_, err := controllerutils.GetAndCreateOrMergePatch(ctx, r.SeedClient, extensionSecret, func() error {
- metav1.SetMetaDataAnnotation(&extensionSecret.ObjectMeta, v1beta1constants.GardenerTimestamp, now)
+ extensionSecret.Annotations = map[string]string{v1beta1constants.GardenerTimestamp: now}
+ extensionSecret.Labels = nil
extensionSecret.Data = credentials.Data
return nil
})
diff --git a/pkg/gardenlet/controller/backupbucket/reconciler_test.go b/pkg/gardenlet/controller/backupbucket/reconciler_test.go
index 20c1d1c0ae0..5820a50bd0a 100644
--- a/pkg/gardenlet/controller/backupbucket/reconciler_test.go
+++ b/pkg/gardenlet/controller/backupbucket/reconciler_test.go
@@ -316,6 +316,22 @@ var _ = Describe("Controller", func() {
Expect(seedClient.Get(ctx, client.ObjectKeyFromObject(extensionBackupBucket), extensionBackupBucket)).To(Succeed())
Expect(extensionBackupBucket.Annotations).To(HaveKey(v1beta1constants.GardenerOperation))
})
+
+ It("should clean the unknown annotations and labels from the extension secret on reconciliation", func() {
+ testKeyValue := map[string]string{"key1": "value1", "key2:": "value2"}
+ extensionSecret.Annotations = testKeyValue // Do not set the timestamp annotation to trigger reconciliation
+ extensionSecret.Labels = testKeyValue
+ Expect(seedClient.Create(ctx, extensionSecret)).To(Succeed())
+ Expect(seedClient.Create(ctx, extensionBackupBucket)).To(Succeed())
+
+ result, err := reconciler.Reconcile(ctx, request)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(result).To(Equal(reconcile.Result{}))
+
+ Expect(seedClient.Get(ctx, client.ObjectKeyFromObject(extensionSecret), extensionSecret)).To(Succeed())
+ Expect(extensionSecret.Annotations).To(Equal(map[string]string{v1beta1constants.GardenerTimestamp: fakeClock.Now().UTC().Format(time.RFC3339Nano)}))
+ Expect(extensionSecret.Labels).To(BeEmpty())
+ })
})
Describe("#WorkloadIdentity Credentials", func() {
diff --git a/pkg/gardenlet/controller/backupentry/reconciler.go b/pkg/gardenlet/controller/backupentry/reconciler.go
index 2f7849e4eb5..0773b0137e0 100644
--- a/pkg/gardenlet/controller/backupentry/reconciler.go
+++ b/pkg/gardenlet/controller/backupentry/reconciler.go
@@ -667,7 +667,8 @@ func (r *Reconciler) reconcileBackupEntryExtensionSecret(ctx context.Context, ex
switch credentials := backupCredentials.(type) {
case *corev1.Secret:
_, err := controllerutils.GetAndCreateOrMergePatch(ctx, r.SeedClient, extensionSecret, func() error {
- metav1.SetMetaDataAnnotation(&extensionSecret.ObjectMeta, v1beta1constants.GardenerTimestamp, now)
+ extensionSecret.Annotations = map[string]string{v1beta1constants.GardenerTimestamp: now}
+ extensionSecret.Labels = nil
extensionSecret.Data = credentials.Data
return nil
})
diff --git a/pkg/gardenlet/controller/backupentry/reconciler_test.go b/pkg/gardenlet/controller/backupentry/reconciler_test.go
index 2d3ece7887e..59e50190e2b 100644
--- a/pkg/gardenlet/controller/backupentry/reconciler_test.go
+++ b/pkg/gardenlet/controller/backupentry/reconciler_test.go
@@ -350,6 +350,23 @@ var _ = Describe("Controller", func() {
"generatedSecret2": []byte("generatedValue2"),
}))
})
+
+ It("should clean the unknown annotations and labels from the extension secret on reconciliation", func() {
+ testKeyValues := map[string]string{"key1": "value1", "key2:": "value2"}
+ extensionSecret.Annotations = testKeyValues // Do not set the timestamp annotation to trigger reconciliation
+ extensionSecret.Labels = testKeyValues
+ Expect(seedClient.Create(ctx, extensionSecret)).To(Succeed())
+ Expect(seedClient.Create(ctx, extensionBackupEntry)).To(Succeed())
+
+ result, err := reconciler.Reconcile(ctx, request)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(result).To(Equal(reconcile.Result{}))
+
+ Expect(seedClient.Get(ctx, client.ObjectKeyFromObject(extensionSecret), extensionSecret)).To(Succeed())
+ Expect(extensionSecret.Annotations).To(Equal(map[string]string{v1beta1constants.GardenerTimestamp: fakeClock.Now().UTC().Format(time.RFC3339Nano)}))
+ Expect(extensionSecret.Labels).To(BeEmpty())
+
+ })
})
Describe("#WorkloadIdentity Credentials", func() {
From 883f8d383e9ba2548b8f50cc5836e979e446f4df Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Wed, 5 Nov 2025 13:07:18 +0100
Subject: [PATCH 035/176] Update opentelemetry-operator to v0.138.0 (#13323)
---
go.mod | 2 +-
go.sum | 4 ++--
imagevector/containers.yaml | 2 +-
...crd-opentelemetry.io_instrumentations.yaml | 7 ++++++
...ntelemetry.io_opentelemetrycollectors.yaml | 24 +++++++++++++++++++
...crd-opentelemetry.io_targetallocators.yaml | 2 ++
6 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/go.mod b/go.mod
index b578bb677c1..7d0539e82c7 100644
--- a/go.mod
+++ b/go.mod
@@ -32,7 +32,7 @@ require (
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/onsi/ginkgo/v2 v2.27.1
github.com/onsi/gomega v1.38.2
- github.com/open-telemetry/opentelemetry-operator v0.137.0
+ github.com/open-telemetry/opentelemetry-operator v0.138.0
github.com/opencontainers/image-spec v1.1.1
github.com/pelletier/go-toml v1.9.5
github.com/perses/perses-operator v0.2.0
diff --git a/go.sum b/go.sum
index a33960d6efe..4fe25342b26 100644
--- a/go.sum
+++ b/go.sum
@@ -576,8 +576,8 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
-github.com/open-telemetry/opentelemetry-operator v0.137.0 h1:RpaTlHGXVRtclYe0kao01SDwvftAfNYV00BuaeJJGxw=
-github.com/open-telemetry/opentelemetry-operator v0.137.0/go.mod h1:RuM1oKvL0W9gNONH1mpV/1g08jGu7LugSl0BOkhuQhk=
+github.com/open-telemetry/opentelemetry-operator v0.138.0 h1:PWNLD3i+sGpPLV2HpTylgGXuJB7iZp4cpoGDtw2XTBo=
+github.com/open-telemetry/opentelemetry-operator v0.138.0/go.mod h1:RuM1oKvL0W9gNONH1mpV/1g08jGu7LugSl0BOkhuQhk=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index a58dc41993f..37774cab9e0 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -188,7 +188,7 @@ images:
- name: opentelemetry-operator
sourceRepository: github.com/open-telemetry/opentelemetry-operator
repository: europe-docker.pkg.dev/gardener-project/releases/3rd/opentelemetry-operator/opentelemetry-operator
- tag: "v0.137.0"
+ tag: "v0.138.0"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
diff --git a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_instrumentations.yaml b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_instrumentations.yaml
index 4ce815cc83d..656a939dad4 100644
--- a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_instrumentations.yaml
+++ b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_instrumentations.yaml
@@ -672,6 +672,7 @@ spec:
description: |-
VolumeSizeLimit defines size limit for volume used for auto-instrumentation.
The default size is 200Mi.
+ Deprecated: use spec..volume.size instead. This field will be inactive in a future release.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
@@ -1133,6 +1134,7 @@ spec:
description: |-
VolumeSizeLimit defines size limit for volume used for auto-instrumentation.
The default size is 200Mi.
+ Deprecated: use spec..volume.size instead. This field will be inactive in a future release.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
@@ -1789,6 +1791,7 @@ spec:
description: |-
VolumeSizeLimit defines size limit for volume used for auto-instrumentation.
The default size is 200Mi.
+ Deprecated: use spec..volume.size instead. This field will be inactive in a future release.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
@@ -2264,6 +2267,7 @@ spec:
description: |-
VolumeSizeLimit defines size limit for volume used for auto-instrumentation.
The default size is 200Mi.
+ Deprecated: use spec..volume.size instead. This field will be inactive in a future release.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
@@ -2879,6 +2883,7 @@ spec:
description: |-
VolumeSizeLimit defines size limit for volume used for auto-instrumentation.
The default size is 200Mi.
+ Deprecated: use spec..volume.size instead. This field will be inactive in a future release.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
@@ -3328,6 +3333,7 @@ spec:
description: |-
VolumeSizeLimit defines size limit for volume used for auto-instrumentation.
The default size is 200Mi.
+ Deprecated: use spec..volume.size instead. This field will be inactive in a future release.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
@@ -3795,6 +3801,7 @@ spec:
description: |-
VolumeSizeLimit defines size limit for volume used for auto-instrumentation.
The default size is 200Mi.
+ Deprecated: use spec..volume.size instead. This field will be inactive in a future release.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object
diff --git a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opentelemetrycollectors.yaml b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opentelemetrycollectors.yaml
index 1e4a435e3ab..b03164db519 100644
--- a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opentelemetrycollectors.yaml
+++ b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_opentelemetrycollectors.yaml
@@ -2678,6 +2678,7 @@ spec:
description: MaxReplicas sets an upper bound to the autoscaling
feature. If MaxReplicas is set autoscaling is enabled.
format: int32
+ minimum: 1
type: integer
metrics:
description: |-
@@ -2809,17 +2810,20 @@ spec:
feature. Set this if you are using autoscaling. It must be
at least 1
format: int32
+ minimum: 1
type: integer
targetCPUUtilization:
description: |-
TargetCPUUtilization sets the target average CPU used across all replicas.
If average CPU exceeds this value, the HPA will scale up. Defaults to 90 percent.
format: int32
+ minimum: 1
type: integer
targetMemoryUtilization:
description: TargetMemoryUtilization sets the target average memory
utilization across all replicas
format: int32
+ minimum: 1
type: integer
type: object
config:
@@ -5103,6 +5107,7 @@ spec:
Minimum consecutive failures for the probe to be considered failed after having succeeded.
Defaults to 3. Minimum value is 1.
format: int32
+ minimum: 1
type: integer
initialDelaySeconds:
description: |-
@@ -5110,18 +5115,21 @@ spec:
Defaults to 0 seconds. Minimum value is 0.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
format: int32
+ minimum: 0
type: integer
periodSeconds:
description: |-
How often (in seconds) to perform the probe.
Default to 10 seconds. Minimum value is 1.
format: int32
+ minimum: 1
type: integer
successThreshold:
description: |-
Minimum consecutive successes for the probe to be considered successful after having failed.
Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1.
format: int32
+ minimum: 1
type: integer
terminationGracePeriodSeconds:
description: |-
@@ -5136,6 +5144,7 @@ spec:
This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate.
Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset.
format: int64
+ minimum: 1
type: integer
timeoutSeconds:
description: |-
@@ -5143,6 +5152,7 @@ spec:
Defaults to 1 second. Minimum value is 1.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
format: int32
+ minimum: 1
type: integer
type: object
managementState:
@@ -5571,6 +5581,8 @@ spec:
description: Allows defining which port to bind to the host
in the Container.
format: int32
+ maximum: 65535
+ minimum: 0
type: integer
name:
description: |-
@@ -5638,6 +5650,7 @@ spec:
Minimum consecutive failures for the probe to be considered failed after having succeeded.
Defaults to 3. Minimum value is 1.
format: int32
+ minimum: 1
type: integer
initialDelaySeconds:
description: |-
@@ -5645,18 +5658,21 @@ spec:
Defaults to 0 seconds. Minimum value is 0.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
format: int32
+ minimum: 0
type: integer
periodSeconds:
description: |-
How often (in seconds) to perform the probe.
Default to 10 seconds. Minimum value is 1.
format: int32
+ minimum: 1
type: integer
successThreshold:
description: |-
Minimum consecutive successes for the probe to be considered successful after having failed.
Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1.
format: int32
+ minimum: 1
type: integer
terminationGracePeriodSeconds:
description: |-
@@ -5671,6 +5687,7 @@ spec:
This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate.
Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset.
format: int64
+ minimum: 1
type: integer
timeoutSeconds:
description: |-
@@ -5678,6 +5695,7 @@ spec:
Defaults to 1 second. Minimum value is 1.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
format: int32
+ minimum: 1
type: integer
type: object
replicas:
@@ -5969,6 +5987,7 @@ spec:
Minimum consecutive failures for the probe to be considered failed after having succeeded.
Defaults to 3. Minimum value is 1.
format: int32
+ minimum: 1
type: integer
initialDelaySeconds:
description: |-
@@ -5976,18 +5995,21 @@ spec:
Defaults to 0 seconds. Minimum value is 0.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
format: int32
+ minimum: 0
type: integer
periodSeconds:
description: |-
How often (in seconds) to perform the probe.
Default to 10 seconds. Minimum value is 1.
format: int32
+ minimum: 1
type: integer
successThreshold:
description: |-
Minimum consecutive successes for the probe to be considered successful after having failed.
Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1.
format: int32
+ minimum: 1
type: integer
terminationGracePeriodSeconds:
description: |-
@@ -6002,6 +6024,7 @@ spec:
This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate.
Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset.
format: int64
+ minimum: 1
type: integer
timeoutSeconds:
description: |-
@@ -6009,6 +6032,7 @@ spec:
Defaults to 1 second. Minimum value is 1.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
format: int32
+ minimum: 1
type: integer
type: object
targetAllocator:
diff --git a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_targetallocators.yaml b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_targetallocators.yaml
index ef04fe2003e..a27df582f9b 100644
--- a/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_targetallocators.yaml
+++ b/pkg/component/observability/opentelemetry/operator/assets/crd-opentelemetry.io_targetallocators.yaml
@@ -4915,6 +4915,8 @@ spec:
description: Allows defining which port to bind to the host
in the Container.
format: int32
+ maximum: 65535
+ minimum: 0
type: integer
name:
description: |-
From fe1f44cd8c09e1a2fb0117560c9acc3a9cfa47e5 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Wed, 5 Nov 2025 13:07:25 +0100
Subject: [PATCH 036/176] Update dependency gardener/vpn2 to v0.44.0 (#13339)
---
imagevector/containers.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index 37774cab9e0..eb2bd901913 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -183,7 +183,7 @@ images:
- name: vpn-server
sourceRepository: github.com/gardener/vpn2
repository: europe-docker.pkg.dev/gardener-project/releases/gardener/vpn-server
- tag: "0.43.0"
+ tag: "0.44.0"
# OpenTelemetry
- name: opentelemetry-operator
sourceRepository: github.com/open-telemetry/opentelemetry-operator
@@ -458,7 +458,7 @@ images:
- name: vpn-client
sourceRepository: github.com/gardener/vpn2
repository: europe-docker.pkg.dev/gardener-project/releases/gardener/vpn-client
- tag: "0.43.0"
+ tag: "0.44.0"
- name: coredns
sourceRepository: github.com/coredns/coredns
repository: registry.k8s.io/coredns/coredns
From 602133e5bc2614ace13cd608beb9dc387910b0f7 Mon Sep 17 00:00:00 2001
From: Sonu Kumar Singh
Date: Wed, 5 Nov 2025 17:37:32 +0530
Subject: [PATCH 037/176] Update backup secret example links in Gardener setup
docs (#13340)
---
docs/deployment/setup_gardener.md | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/docs/deployment/setup_gardener.md b/docs/deployment/setup_gardener.md
index 21f4b40588a..ecb4dbda331 100644
--- a/docs/deployment/setup_gardener.md
+++ b/docs/deployment/setup_gardener.md
@@ -288,7 +288,12 @@ To obtain credentials and interact with the virtual Garden cluster, please follo
Reference documentation and examples:
- [Garden configuration example](../../example/operator/20-garden.yaml)
-- [Backup secret examples](https://github.com/gardener/etcd-backup-restore/tree/master/example/storage-provider-secrets)
+- Backup secret examples
+ - [Alicloud](https://github.com/gardener/gardener-extension-provider-alicloud/blob/master/example/30-etcd-backup-secret.yaml)
+ - [AWS](https://github.com/gardener/gardener-extension-provider-aws/blob/master/example/30-etcd-backup-secret.yaml)
+ - [Azure](https://github.com/gardener/gardener-extension-provider-azure/blob/master/example/30-etcd-backup-secret.yaml)
+ - [GCP](https://github.com/gardener/gardener-extension-provider-gcp/blob/master/example/30-etcd-backup-secret.yaml)
+ - [OpenStack](https://github.com/gardener/gardener-extension-provider-openstack/blob/master/example/30-etcd-backup-secret.yaml)
- [Configuration options](../concepts/operator.md#garden-resources)
- [Accessing the virtual Garden](../concepts/operator.md#virtual-garden-kubeconfig)
From 66c5e058c9db2efda4a96a45482c5258884d67ee Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Wed, 5 Nov 2025 13:07:38 +0100
Subject: [PATCH 038/176] Update dependency golangci/golangci-lint to v2.6.1
(#13343)
---
hack/tools.mk | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hack/tools.mk b/hack/tools.mk
index 876511c8741..2217843c385 100644
--- a/hack/tools.mk
+++ b/hack/tools.mk
@@ -54,7 +54,7 @@ TYPOS := $(TOOLS_BIN_DIR)/typos
# default tool versions
# renovate: datasource=github-releases depName=golangci/golangci-lint
-GOLANGCI_LINT_VERSION ?= v2.6.0
+GOLANGCI_LINT_VERSION ?= v2.6.1
# renovate: datasource=github-releases depName=securego/gosec
GOSEC_VERSION ?= v2.22.10
# renovate: datasource=github-releases depName=joelanford/go-apidiff
From fd3a5cf00e23e51dbadae6cf0f18ff4f7473bfe8 Mon Sep 17 00:00:00 2001
From: Marin Atanasov Nikolov
Date: Wed, 5 Nov 2025 14:07:45 +0200
Subject: [PATCH 039/176] docs/extensions: fix link to known extension
implementations (#13359)
---
docs/extensions/overview.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/extensions/overview.md b/docs/extensions/overview.md
index f808d6b4cb3..c97114e2469 100644
--- a/docs/extensions/overview.md
+++ b/docs/extensions/overview.md
@@ -185,4 +185,4 @@ We are truly looking forward to your feedback!
## Known Extensions
-We track all extensions of Gardener in the [known Gardener Extensions List](../README.md#known-extension-implementations) repo.
+We track all extensions of Gardener in the [known Gardener Extensions List](../../extensions/README.md#known-extension-implementations) repo.
From be542101dcf8575c04627e659b11501b94342487 Mon Sep 17 00:00:00 2001
From: Indrit Fejza
Date: Wed, 5 Nov 2025 14:49:19 +0100
Subject: [PATCH 040/176] add new panel for node load average to the node
details dashboard (#13280)
* add new panel for node load average
* revert unneeded changes
* do now change ips
* use fill 0
* add Node to title to be in line with the other panels
---
.../owners/worker/node-details-dashboard.json | 126 ++++++++++++++++--
1 file changed, 115 insertions(+), 11 deletions(-)
diff --git a/pkg/component/observability/plutono/dashboards/shoot/owners/worker/node-details-dashboard.json b/pkg/component/observability/plutono/dashboards/shoot/owners/worker/node-details-dashboard.json
index c4350029860..2d24b414ffa 100644
--- a/pkg/component/observability/plutono/dashboards/shoot/owners/worker/node-details-dashboard.json
+++ b/pkg/component/observability/plutono/dashboards/shoot/owners/worker/node-details-dashboard.json
@@ -16,8 +16,7 @@
"editable": true,
"gnetId": 2115,
"graphTooltip": 0,
- "id": 32,
- "iteration": 1622621007137,
+ "iteration": 1761637646458,
"links": [],
"panels": [
{
@@ -107,7 +106,7 @@
"showThresholdMarkers": true,
"text": {}
},
- "pluginVersion": "7.5.16",
+ "pluginVersion": "7.5.43",
"targets": [
{
"expr": "sum(rate(node_cpu_seconds_total{mode=~\"system|user|irq|softirq\", node=~\"$Node\"}[$__rate_interval])) / sum(kube_node_status_capacity{resource=\"cpu\", unit=\"core\", node=~\"$Node\"}) * 100",
@@ -195,7 +194,7 @@
"showThresholdMarkers": true,
"text": {}
},
- "pluginVersion": "7.5.16",
+ "pluginVersion": "7.5.43",
"targets": [
{
"expr": "sum((node_memory_MemTotal_bytes{node=~\"$Node\"} - node_memory_MemAvailable_bytes{node=~\"$Node\"}) / node_memory_MemTotal_bytes{node=~\"$Node\"}) * 100",
@@ -253,7 +252,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.16",
+ "pluginVersion": "7.5.43",
"pointradius": 2,
"points": false,
"renderer": "flot",
@@ -383,7 +382,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.16",
+ "pluginVersion": "7.5.43",
"pointradius": 2,
"points": false,
"renderer": "flot",
@@ -517,7 +516,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.16",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
@@ -633,7 +632,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.16",
+ "pluginVersion": "7.5.43",
"pointradius": 2,
"points": false,
"renderer": "flot",
@@ -707,6 +706,111 @@
"alignLevel": null
}
},
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "description": "Load average figure gives the number of jobs in the run queue (state R) or waiting for disk I/O (state D) averaged over 1 minute. See https://linux.die.net/man/5/proc",
+ "fieldConfig": {
+ "defaults": {},
+ "overrides": []
+ },
+ "fill": 0,
+ "fillGradient": 0,
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 23
+ },
+ "hiddenSeries": false,
+ "id": 84,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": true,
+ "max": true,
+ "min": false,
+ "rightSide": false,
+ "show": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "nullPointMode": "null",
+ "options": {
+ "alertThreshold": true
+ },
+ "percentage": false,
+ "pluginVersion": "7.5.43",
+ "pointradius": 2,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "exemplar": true,
+ "expr": "node_load1{node=\"$Node\"}",
+ "interval": "",
+ "legendFormat": "Load Average (1min)",
+ "refId": "A"
+ },
+ {
+ "exemplar": true,
+ "expr": "sum(kube_node_status_capacity{resource=\"cpu\", unit=\"core\", node=~\"$Node\"}) ",
+ "hide": false,
+ "interval": "",
+ "legendFormat": "CPU count",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeRegions": [],
+ "timeShift": null,
+ "title": "System Load Average ($Node)",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
{
"collapsed": false,
"datasource": null,
@@ -759,7 +863,7 @@
"alertThreshold": false
},
"percentage": false,
- "pluginVersion": "7.5.16",
+ "pluginVersion": "7.5.43",
"pointradius": 2,
"points": false,
"renderer": "flot",
@@ -892,7 +996,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.16",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
@@ -1016,7 +1120,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.16",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
From a0d0a160768615a56ec71bfe18eb4dc2b1eeac1a Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Wed, 5 Nov 2025 14:49:26 +0100
Subject: [PATCH 041/176] Update module sigs.k8s.io/controller-runtime to
v0.22.4 (#13333)
---
go.mod | 2 +-
go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/go.mod b/go.mod
index 7d0539e82c7..96718ac8ab4 100644
--- a/go.mod
+++ b/go.mod
@@ -82,7 +82,7 @@ require (
k8s.io/metrics v0.34.1
k8s.io/pod-security-admission v0.34.1
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4
- sigs.k8s.io/controller-runtime v0.22.3
+ sigs.k8s.io/controller-runtime v0.22.4
sigs.k8s.io/controller-tools v0.19.0
sigs.k8s.io/yaml v1.6.0
)
diff --git a/go.sum b/go.sum
index 4fe25342b26..bd38ba64b76 100644
--- a/go.sum
+++ b/go.sum
@@ -1153,8 +1153,8 @@ oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
-sigs.k8s.io/controller-runtime v0.22.3 h1:I7mfqz/a/WdmDCEnXmSPm8/b/yRTy6JsKKENTijTq8Y=
-sigs.k8s.io/controller-runtime v0.22.3/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
+sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A=
+sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
sigs.k8s.io/controller-tools v0.19.0 h1:OU7jrPPiZusryu6YK0jYSjPqg8Vhf8cAzluP9XGI5uk=
sigs.k8s.io/controller-tools v0.19.0/go.mod h1:y5HY/iNDFkmFla2CfQoVb2AQXMsBk4ad84iR1PLANB0=
sigs.k8s.io/gateway-api v1.3.0 h1:q6okN+/UKDATola4JY7zXzx40WO4VISk7i9DIfOvr9M=
From 7372984bbac610633357dca087481e82e433ffaa Mon Sep 17 00:00:00 2001
From: Tim Ebert
Date: Wed, 5 Nov 2025 14:49:33 +0100
Subject: [PATCH 042/176] [GEP-28] Unify `gardenadm` node directories (#13357)
---
pkg/gardenadm/cmd/options_manifests.go | 4 +++-
test/e2e/gardenadm/unmanagedinfra/gardenadm.go | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/pkg/gardenadm/cmd/options_manifests.go b/pkg/gardenadm/cmd/options_manifests.go
index 870cac8fb36..8a66ba23112 100644
--- a/pkg/gardenadm/cmd/options_manifests.go
+++ b/pkg/gardenadm/cmd/options_manifests.go
@@ -8,6 +8,8 @@ import (
"fmt"
"github.com/spf13/pflag"
+
+ "github.com/gardener/gardener/pkg/gardenadm/botanist"
)
// ManifestOptions contains options related to handling the manifest files.
@@ -40,4 +42,4 @@ func (o *ManifestOptions) AddFlags(fs *pflag.FlagSet) {
}
// ConfigDirLocation is the location where `gardenadm init` stores the config directory path.
-const ConfigDirLocation = "/etc/gardenadm/config-directory"
+const ConfigDirLocation = botanist.GardenadmBaseDir + "/config-directory"
diff --git a/test/e2e/gardenadm/unmanagedinfra/gardenadm.go b/test/e2e/gardenadm/unmanagedinfra/gardenadm.go
index 5d855321a9d..fb165b7f1ef 100644
--- a/test/e2e/gardenadm/unmanagedinfra/gardenadm.go
+++ b/test/e2e/gardenadm/unmanagedinfra/gardenadm.go
@@ -200,7 +200,7 @@ var _ = Describe("gardenadm unmanaged infrastructure scenario tests", Label("gar
It("should ensure that the config dir location has been stored in the well-known location", func(ctx SpecContext) {
Eventually(ctx, func(g Gomega) string {
- stdOut, _, err := execute(ctx, 0, "cat", "/etc/gardenadm/config-directory")
+ stdOut, _, err := execute(ctx, 0, "cat", "/var/lib/gardenadm/config-directory")
g.Expect(err).NotTo(HaveOccurred())
return string(stdOut.Contents())
}).Should(Equal(configDirectory))
From f4d12a02a5fe2da94c5a4b1fad1e6ff7dc4f3107 Mon Sep 17 00:00:00 2001
From: Tobias Schlicht <155947440+tobschli@users.noreply.github.com>
Date: Wed, 5 Nov 2025 16:39:20 +0100
Subject: [PATCH 043/176] Non-namespaced resource limits (#12916)
* Add optional `Count` parameter to resource limit webhook
* Adapt components, tests and conversions to take the, now optional `size` limit
* Adapt resourcesize handler to also handle `count` limit
* Add tests for `count` limit handling
* Add validation for `count` field
* Add tests for `count` validation
* --- SEPARATOR ---
* Adapt `admission-controller` `ConfigMap` template to not add keys, when values are empty.
Before this, when not specifying e.g. `unrestrictedSubjects`, the key would be added to the YAML, leading to invalid YAML
* Adapt documentation
* Limit the list to `countLimit + 1`
This also included some refactorings, as we did not return an error when the evaluation of the current count of objects fails, to prevent this feature from blocking operations on the objects.
* Add logging to hint that limits are only enforced for non-namespaced resources
* Fix test by adding rest mapper
* Implement PR feedback
* Implement PR feedback
* Implement PR feedback
* Adapt API description of `Count` filed
Co-authored-by: Tim Usner
* Fix wording
Co-authored-by: Rafael Franzke
* Inline variables that are only used once
Co-authored-by: Rafael Franzke
---------
Co-authored-by: Tim Usner
Co-authored-by: Rafael Franzke
---
.../configmap-componentconfig.yaml | 4 +
charts/gardener/controlplane/values.yaml | 4 +
.../operator/templates/crd-gardens.yaml | 7 +-
docs/api-reference/operator.md | 13 ++
docs/concepts/admission-controller.md | 9 ++
...tconfig-gardener-admission-controller.yaml | 4 +
...0-crd-operator.gardener.cloud_gardens.yaml | 7 +-
example/operator/20-garden.yaml | 4 +
.../apis/config/v1alpha1/types.go | 8 +-
.../config/v1alpha1/validation/validation.go | 11 +-
.../v1alpha1/validation/validation_test.go | 27 ++--
.../config/v1alpha1/zz_generated.deepcopy.go | 11 +-
pkg/admissioncontroller/webhook/add.go | 6 +-
.../webhook/admission/resourcesize/handler.go | 129 ++++++++++++++++--
.../admission/resourcesize/handler_test.go | 98 +++++++++----
.../v1alpha1/conversion/conversion.go | 1 +
.../v1alpha1/conversion/conversion_test.go | 5 +-
pkg/apis/operator/v1alpha1/types_garden.go | 6 +-
.../v1alpha1/validation/garden_test.go | 2 +-
.../v1alpha1/zz_generated.deepcopy.go | 11 +-
.../admission_controller_test.go | 4 +-
21 files changed, 307 insertions(+), 64 deletions(-)
diff --git a/charts/gardener/controlplane/charts/runtime/templates/admission-controller/configmap-componentconfig.yaml b/charts/gardener/controlplane/charts/runtime/templates/admission-controller/configmap-componentconfig.yaml
index 829c93bb420..14015534b56 100644
--- a/charts/gardener/controlplane/charts/runtime/templates/admission-controller/configmap-componentconfig.yaml
+++ b/charts/gardener/controlplane/charts/runtime/templates/admission-controller/configmap-componentconfig.yaml
@@ -52,10 +52,14 @@ data:
port: {{ required ".Values.global.admission.config.server.metrics.port is required" .Values.global.admission.config.server.metrics.port }}
{{- if .Values.global.admission.config.server.resourceAdmissionConfiguration }}
resourceAdmissionConfiguration:
+ {{- if .Values.global.admission.config.server.resourceAdmissionConfiguration.limits }}
limits:
{{ toYaml .Values.global.admission.config.server.resourceAdmissionConfiguration.limits | indent 8 }}
+ {{- end }}
+ {{- if .Values.global.admission.config.server.resourceAdmissionConfiguration.unrestrictedSubjects }}
unrestrictedSubjects:
{{ toYaml .Values.global.admission.config.server.resourceAdmissionConfiguration.unrestrictedSubjects | indent 8 }}
+ {{- end }}
operationMode: {{ required ".Values.global.admission.config.server.resourceAdmissionConfiguration.operationMode is required" .Values.global.admission.config.server.resourceAdmissionConfiguration.operationMode }}
{{- end }}
enableDebugHandlers: {{ .Values.global.admission.config.server.enableDebugHandlers }}
diff --git a/charts/gardener/controlplane/values.yaml b/charts/gardener/controlplane/values.yaml
index 3801f89fe31..951c857227c 100644
--- a/charts/gardener/controlplane/values.yaml
+++ b/charts/gardener/controlplane/values.yaml
@@ -313,6 +313,10 @@ global:
# apiVersions: ["*"]
# resources: ["shoots"]
# size: 100Ki
+ # - apiGroups: ["core.gardener.cloud"]
+ # apiVersions: ["*"]
+ # resources: ["projects"]
+ # count: 200
# unrestrictedSubjects:
# - kind: Group
# name: gardener.cloud:system:seeds
diff --git a/charts/gardener/operator/templates/crd-gardens.yaml b/charts/gardener/operator/templates/crd-gardens.yaml
index 1892a6751c3..7d31146cc7c 100644
--- a/charts/gardener/operator/templates/crd-gardens.yaml
+++ b/charts/gardener/operator/templates/crd-gardens.yaml
@@ -800,6 +800,12 @@ spec:
items:
type: string
type: array
+ count:
+ description: Count specifies the maximum number
+ of resources of the given kind. Only cluster-scoped
+ resources are considered.
+ format: int64
+ type: integer
resources:
description: Resources is the name of the resource
this rule applies to. WildcardAll represents
@@ -816,7 +822,6 @@ spec:
x-kubernetes-int-or-string: true
required:
- resources
- - size
type: object
type: array
operationMode:
diff --git a/docs/api-reference/operator.md b/docs/api-reference/operator.md
index cbbc54ee0cc..27573f77627 100644
--- a/docs/api-reference/operator.md
+++ b/docs/api-reference/operator.md
@@ -2930,9 +2930,22 @@ k8s.io/apimachinery/pkg/api/resource.Quantity
+(Optional)
Size specifies the imposed limit.
+
+
+count
+
+int64
+
+
+
+(Optional)
+
Count specifies the maximum number of resources of the given kind. Only cluster-scoped resources are considered.
+
+
RuntimeCluster
diff --git a/docs/concepts/admission-controller.md b/docs/concepts/admission-controller.md
index 07a79df6dbd..456a40b55b1 100644
--- a/docs/concepts/admission-controller.md
+++ b/docs/concepts/admission-controller.md
@@ -59,6 +59,10 @@ server:
apiVersions: ["*"]
resources: ["shoots"]
size: 100k
+ - apiGroups: ["core.gardener.cloud"]
+ apiVersions: ["*"]
+ resources: ["projects"]
+ count: 200
- apiGroups: [""]
apiVersions: ["v1"]
resources: ["secrets"]
@@ -89,6 +93,11 @@ Size limitations depend on the individual Gardener setup and choosing the wrong
`resourceAdmissionConfiguration.operationMode` allows to control if a violating request is actually denied (default) or only logged.
It's recommended to start with `log`, check the logs for exceeding requests, adjust the limits if necessary and finally switch to `block`.
+In addition to that, it is also possible to restrict the number of **cluster-scoped** resources, using the `count` field, like in the example above.
+This ensures that only a certain number of resources of the given type can exist in the cluster.
+Similar to restrictions, subjects configured under `unrestrictedSubjects` are exempt from this restriction.
+The count restriction can also be used in combination with size restrictions.
+
### SeedRestriction
Please refer to [Scoped API Access for Gardenlets](../deployment/gardenlet_api_access.md) for more information.
diff --git a/example/20-componentconfig-gardener-admission-controller.yaml b/example/20-componentconfig-gardener-admission-controller.yaml
index 174eb804f38..a66be369b6e 100644
--- a/example/20-componentconfig-gardener-admission-controller.yaml
+++ b/example/20-componentconfig-gardener-admission-controller.yaml
@@ -21,6 +21,10 @@ server:
apiVersions: ["*"]
resources: ["shoots"]
size: 100k
+ - apiGroups: [ "core.gardener.cloud" ]
+ apiVersions: [ "*" ]
+ resources: [ "projects" ]
+ count: 200
unrestrictedSubjects:
- kind: Group
name: gardener.cloud:system:seeds
diff --git a/example/operator/10-crd-operator.gardener.cloud_gardens.yaml b/example/operator/10-crd-operator.gardener.cloud_gardens.yaml
index 1892a6751c3..7d31146cc7c 100644
--- a/example/operator/10-crd-operator.gardener.cloud_gardens.yaml
+++ b/example/operator/10-crd-operator.gardener.cloud_gardens.yaml
@@ -800,6 +800,12 @@ spec:
items:
type: string
type: array
+ count:
+ description: Count specifies the maximum number
+ of resources of the given kind. Only cluster-scoped
+ resources are considered.
+ format: int64
+ type: integer
resources:
description: Resources is the name of the resource
this rule applies to. WildcardAll represents
@@ -816,7 +822,6 @@ spec:
x-kubernetes-int-or-string: true
required:
- resources
- - size
type: object
type: array
operationMode:
diff --git a/example/operator/20-garden.yaml b/example/operator/20-garden.yaml
index eca42aa9031..829fd259531 100644
--- a/example/operator/20-garden.yaml
+++ b/example/operator/20-garden.yaml
@@ -250,6 +250,10 @@ spec:
# apiVersions: ["*"]
# resources: ["shoots"]
# size: 100k
+ # - apiGroups: ["core.gardener.cloud"]
+ # apiVersions: ["*"]
+ # resources: ["projects"]
+ # count: 200
# unrestrictedSubjects:
# - kind: Group
# name: gardener.cloud:system:seeds
diff --git a/pkg/admissioncontroller/apis/config/v1alpha1/types.go b/pkg/admissioncontroller/apis/config/v1alpha1/types.go
index 447442079a8..172fdff33fa 100644
--- a/pkg/admissioncontroller/apis/config/v1alpha1/types.go
+++ b/pkg/admissioncontroller/apis/config/v1alpha1/types.go
@@ -69,7 +69,7 @@ type ResourceAdmissionWebhookMode string
// WildcardAll is a character which represents all elements in a set.
const WildcardAll = "*"
-// ResourceLimit contains settings about a kind and the size each resource should have at most.
+// ResourceLimit contains settings about a kind and the size as well as count each resource should have at most.
type ResourceLimit struct {
// APIGroups is the name of the APIGroup that contains the limited resource. WildcardAll represents all groups.
// +optional
@@ -80,7 +80,11 @@ type ResourceLimit struct {
// Resources is the name of the resource this rule applies to. WildcardAll represents all resources.
Resources []string `json:"resources"`
// Size specifies the imposed limit.
- Size resource.Quantity `json:"size"`
+ // +optional
+ Size *resource.Quantity `json:"size,omitempty"`
+ // Count specifies the maximum number of resources of the given kind. Only cluster-scoped resources are considered.
+ // +optional
+ Count *int64 `json:"count,omitempty"`
}
// Server contains information for HTTP(S) server configuration.
diff --git a/pkg/admissioncontroller/apis/config/v1alpha1/validation/validation.go b/pkg/admissioncontroller/apis/config/v1alpha1/validation/validation.go
index 64175d6ae32..953ba821421 100644
--- a/pkg/admissioncontroller/apis/config/v1alpha1/validation/validation.go
+++ b/pkg/admissioncontroller/apis/config/v1alpha1/validation/validation.go
@@ -7,6 +7,7 @@ package validation
import (
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/resource"
+ apivalidation "k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
@@ -112,7 +113,15 @@ func ValidateResourceAdmissionConfiguration(config *admissioncontrollerconfigv1a
allErrs = append(allErrs, field.Invalid(fld.Child("versions"), limit.Resources, "must at least have one element"))
}
- if limit.Size.Cmp(resource.Quantity{}) < 0 {
+ if limit.Count == nil && limit.Size == nil {
+ allErrs = append(allErrs, field.Invalid(fld, limit, "at least one of size or count must be specified"))
+ }
+
+ if limit.Count != nil && apivalidation.ValidateNonnegativeField(*limit.Count, fld.Child("count")).ToAggregate() != nil {
+ allErrs = append(allErrs, field.Invalid(fld.Child("count"), limit.Count, "value must not be negative"))
+ }
+
+ if limit.Size != nil && limit.Size.Cmp(resource.Quantity{}) < 0 {
allErrs = append(allErrs, field.Invalid(fld.Child("size"), limit.Size.String(), "value must not be negative"))
}
}
diff --git a/pkg/admissioncontroller/apis/config/v1alpha1/validation/validation_test.go b/pkg/admissioncontroller/apis/config/v1alpha1/validation/validation_test.go
index 6b927023f04..7a0837909a4 100644
--- a/pkg/admissioncontroller/apis/config/v1alpha1/validation/validation_test.go
+++ b/pkg/admissioncontroller/apis/config/v1alpha1/validation/validation_test.go
@@ -95,10 +95,11 @@ var _ = Describe("#ValidateAdmissionControllerConfiguration", func() {
versions = []string{"v1beta1", "v1alpha1"}
resources = []string{"shoot"}
size = "1Ki"
+ count = int64(100)
)
DescribeTable("Limits validation",
- func(apiGroups []string, versions []string, resources []string, size string, matcher gomegatypes.GomegaMatcher) {
+ func(apiGroups []string, versions []string, resources []string, size string, count int64, matcher gomegatypes.GomegaMatcher) {
s, err := resource.ParseQuantity(size)
utilruntime.Must(err)
config := &admissioncontrollerconfigv1alpha1.AdmissionControllerConfiguration{
@@ -111,7 +112,8 @@ var _ = Describe("#ValidateAdmissionControllerConfiguration", func() {
APIGroups: apiGroups,
APIVersions: versions,
Resources: resources,
- Size: s,
+ Size: &s,
+ Count: &count,
},
},
},
@@ -123,36 +125,39 @@ var _ = Describe("#ValidateAdmissionControllerConfiguration", func() {
Expect(errs).To(matcher)
},
- Entry("should allow request", apiGroups, versions, resources, size,
+ Entry("should allow request", apiGroups, versions, resources, size, count,
BeEmpty(),
),
- Entry("should deny empty apiGroup", nil, versions, resources, size,
+ Entry("should deny empty apiGroup", nil, versions, resources, size, count,
ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{"Field": Equal("server.resourceAdmissionConfiguration.limits[0].apiGroups")}))),
),
- Entry("should allow apiGroup w/ zero length", []string{""}, versions, resources, size,
+ Entry("should allow apiGroup w/ zero length", []string{""}, versions, resources, size, count,
BeEmpty(),
),
- Entry("should deny empty versions", apiGroups, nil, resources, size,
+ Entry("should deny empty versions", apiGroups, nil, resources, size, count,
ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{"Field": Equal("server.resourceAdmissionConfiguration.limits[0].versions")}))),
),
- Entry("should deny versions w/ zero length", apiGroups, []string{""}, resources, size,
+ Entry("should deny versions w/ zero length", apiGroups, []string{""}, resources, size, count,
ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{"Field": Equal("server.resourceAdmissionConfiguration.limits[0].versions[0]")}))),
),
- Entry("should deny empty resources", apiGroups, versions, nil, size,
+ Entry("should deny empty resources", apiGroups, versions, nil, size, count,
ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{"Field": Equal("server.resourceAdmissionConfiguration.limits[0].resources")}))),
),
- Entry("should deny resources w/ zero length", apiGroups, versions, []string{""}, size,
+ Entry("should deny resources w/ zero length", apiGroups, versions, []string{""}, size, count,
ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{"Field": Equal("server.resourceAdmissionConfiguration.limits[0].resources[0]")}))),
),
- Entry("should deny invalid size", apiGroups, versions, resources, "-1k",
+ Entry("should deny invalid size", apiGroups, versions, resources, "-1k", count,
ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{"Field": Equal("server.resourceAdmissionConfiguration.limits[0].size")}))),
),
- Entry("should deny invalid size and resources w/ zero length", apiGroups, versions, []string{resources[0], ""}, "-1k",
+ Entry("should deny invalid size and resources w/ zero length", apiGroups, versions, []string{resources[0], ""}, "-1k", count,
ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{"Field": Equal("server.resourceAdmissionConfiguration.limits[0].size")})),
PointTo(MatchFields(IgnoreExtras, Fields{"Field": Equal("server.resourceAdmissionConfiguration.limits[0].resources[1]")})),
),
),
+ Entry("should deny invalid count", apiGroups, versions, resources, size, int64(-1),
+ ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{"Field": Equal("server.resourceAdmissionConfiguration.limits[0].count")}))),
+ ),
)
var (
diff --git a/pkg/admissioncontroller/apis/config/v1alpha1/zz_generated.deepcopy.go b/pkg/admissioncontroller/apis/config/v1alpha1/zz_generated.deepcopy.go
index 9c102649f74..94a461b23f3 100644
--- a/pkg/admissioncontroller/apis/config/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/admissioncontroller/apis/config/v1alpha1/zz_generated.deepcopy.go
@@ -116,7 +116,16 @@ func (in *ResourceLimit) DeepCopyInto(out *ResourceLimit) {
*out = make([]string, len(*in))
copy(*out, *in)
}
- out.Size = in.Size.DeepCopy()
+ if in.Size != nil {
+ in, out := &in.Size, &out.Size
+ x := (*in).DeepCopy()
+ *out = &x
+ }
+ if in.Count != nil {
+ in, out := &in.Count, &out.Count
+ *out = new(int64)
+ **out = **in
+ }
return
}
diff --git a/pkg/admissioncontroller/webhook/add.go b/pkg/admissioncontroller/webhook/add.go
index 941e141e7fa..50b563ec153 100644
--- a/pkg/admissioncontroller/webhook/add.go
+++ b/pkg/admissioncontroller/webhook/add.go
@@ -82,8 +82,10 @@ func AddToManager(
}
if err := (&resourcesize.Handler{
- Logger: mgr.GetLogger().WithName("webhook").WithName(resourcesize.HandlerName),
- Config: cfg.Server.ResourceAdmissionConfiguration,
+ Logger: mgr.GetLogger().WithName("webhook").WithName(resourcesize.HandlerName),
+ Config: cfg.Server.ResourceAdmissionConfiguration,
+ APIReader: mgr.GetAPIReader(),
+ RESTMapper: mgr.GetRESTMapper(),
}).AddToManager(mgr); err != nil {
return fmt.Errorf("failed adding %s webhook handler: %w", resourcesize.HandlerName, err)
}
diff --git a/pkg/admissioncontroller/webhook/admission/resourcesize/handler.go b/pkg/admissioncontroller/webhook/admission/resourcesize/handler.go
index 0f060c85211..b96a0cef908 100644
--- a/pkg/admissioncontroller/webhook/admission/resourcesize/handler.go
+++ b/pkg/admissioncontroller/webhook/admission/resourcesize/handler.go
@@ -10,17 +10,21 @@ import (
"fmt"
"net/http"
"strings"
+ "time"
"github.com/go-logr/logr"
admissionv1 "k8s.io/api/admission/v1"
authenticationv1 "k8s.io/api/authentication/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/apiserver/pkg/authentication/serviceaccount"
+ "k8s.io/utils/ptr"
+ "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
admissioncontrollerconfigv1alpha1 "github.com/gardener/gardener/pkg/admissioncontroller/apis/config/v1alpha1"
@@ -28,24 +32,31 @@ import (
"github.com/gardener/gardener/pkg/admissioncontroller/metrics"
)
-// metricReasonSizeExceeded is a metric reason value for a reason when an object size was exceeded.
-const metricReasonSizeExceeded = "Size Exceeded"
+const (
+ // metricReasonSizeExceeded is a metric reason value for a reason when an object size was exceeded.
+ metricReasonSizeExceeded = "Size Exceeded"
+
+ // metricReasonCountExceeded is a metric reason value for a reason when resource count was exceeded.
+ metricReasonCountExceeded = "Count Exceeded"
+)
// Handler checks the resource sizes.
type Handler struct {
- Logger logr.Logger
- Config *admissioncontrollerconfigv1alpha1.ResourceAdmissionConfiguration
+ Logger logr.Logger
+ Config *admissioncontrollerconfigv1alpha1.ResourceAdmissionConfiguration
+ APIReader client.Reader
+ RESTMapper meta.RESTMapper
}
// Handle checks the resource sizes.
-func (h *Handler) Handle(_ context.Context, req admission.Request) admission.Response {
+func (h *Handler) Handle(ctx context.Context, req admission.Request) admission.Response {
var err error
switch req.Operation {
case admissionv1.Create:
- err = h.handle(req)
+ err = h.handle(ctx, req)
case admissionv1.Update:
- err = h.handle(req)
+ err = h.handle(ctx, req)
default:
return admission.Errored(http.StatusBadRequest, fmt.Errorf("unknown operation request %q", req.Operation))
}
@@ -62,7 +73,7 @@ func (h *Handler) Handle(_ context.Context, req admission.Request) admission.Res
return admission.Allowed("")
}
-func (h *Handler) handle(req admission.Request) error {
+func (h *Handler) handle(ctx context.Context, req admission.Request) error {
log := h.Logger.WithValues("user", req.UserInfo.Username, "resource", req.Resource, "name", req.Name)
if req.Namespace != "" {
log = log.WithValues("namespace", req.Namespace)
@@ -78,11 +89,29 @@ func (h *Handler) handle(req admission.Request) error {
requestedResource = req.RequestResource
}
- limit := findLimitForGVR(h.Config.Limits, requestedResource)
- if limit == nil {
+ limit, count := findRestrictionsForGVR(h.Config.Limits, requestedResource)
+ if limit == nil && count == nil {
return nil
}
+ // Handle resource count limits
+ if count != nil {
+ if err := h.handleCountLimit(ctx, req, log, requestedResource, count); err != nil {
+ return fmt.Errorf("error handling count limit: %w", err)
+ }
+ }
+
+ // Handle resource size limits
+ if limit != nil {
+ if err := h.handleSizeLimit(req, log, limit); err != nil {
+ return fmt.Errorf("error handling size limit: %w", err)
+ }
+ }
+
+ return nil
+}
+
+func (h *Handler) handleSizeLimit(req admission.Request, log logr.Logger, limit *resource.Quantity) error {
objectSize, err := relevantObjectSize(req.Object.Raw)
if err != nil {
return err
@@ -105,6 +134,43 @@ func (h *Handler) handle(req admission.Request) error {
return nil
}
+func (h *Handler) handleCountLimit(ctx context.Context, req admission.Request, log logr.Logger, requestedResource *metav1.GroupVersionResource, count *int64) error {
+ if req.Namespace != "" {
+ // We only want to restrict non-namespaced resources
+ // namespaced resources can be restricted by ResourceQuotas
+ log.Info("Skipping count check for namespaced resource", "resource", requestedResource.String())
+ return nil
+ }
+
+ // Only count for CREATE operations, not UPDATE
+ if req.Operation != admissionv1.Create {
+ return nil
+ }
+
+ exceedsLimit, err := h.existingResourcesExceedLimit(ctx, req, requestedResource, ptr.Deref(count, 0))
+ if err != nil {
+ return fmt.Errorf("failed to determine if count exceeds limit: %w", err)
+ }
+
+ if !exceedsLimit {
+ return nil
+ }
+
+ if h.Config.OperationMode == nil || *h.Config.OperationMode == admissioncontrollerconfigv1alpha1.AdmissionModeBlock {
+ log.Info("Maximum resource count exceeded, rejected request", "limit", *count)
+ metrics.RejectedResources.WithLabelValues(
+ fmt.Sprint(req.Operation),
+ req.Kind.Kind,
+ req.Namespace,
+ metricReasonCountExceeded,
+ ).Inc()
+ return apierrors.NewForbidden(schema.GroupResource{Group: req.Resource.Group, Resource: req.Resource.Resource}, req.Name, fmt.Errorf("maximum resource count exceeded! max allowed: %d", ptr.Deref(count, 0)))
+ }
+
+ log.Info("Maximum resource count exceeded, request would be denied in blocking mode", "limit", ptr.Deref(count, 0))
+ return nil
+}
+
func relevantObjectSize(rawObject []byte) (int64, error) {
var obj map[string]any
err := json.Unmarshal(rawObject, &obj)
@@ -155,14 +221,49 @@ func isUnrestrictedUser(userInfo authenticationv1.UserInfo, subjects []rbacv1.Su
return userMatch(userInfo, subjects)
}
-func findLimitForGVR(limits []admissioncontrollerconfigv1alpha1.ResourceLimit, gvr *metav1.GroupVersionResource) *resource.Quantity {
+func findRestrictionsForGVR(limits []admissioncontrollerconfigv1alpha1.ResourceLimit, gvr *metav1.GroupVersionResource) (*resource.Quantity, *int64) {
for _, limit := range limits {
- size := limit.Size
if admissioncontrollerhelper.APIGroupMatches(limit, gvr.Group) &&
admissioncontrollerhelper.VersionMatches(limit, gvr.Version) &&
admissioncontrollerhelper.ResourceMatches(limit, gvr.Resource) {
- return &size
+ return limit.Size, limit.Count
}
}
- return nil
+ return nil, nil
+}
+
+func (h *Handler) getKindFromGVR(gvr *metav1.GroupVersionResource) (string, error) {
+ gvk, err := h.RESTMapper.KindFor(schema.GroupVersionResource{
+ Group: gvr.Group,
+ Version: gvr.Version,
+ Resource: gvr.Resource,
+ })
+ if err != nil {
+ return "", fmt.Errorf("failed to get Kind for GVR %s: %w", gvr.String(), err)
+ }
+ return gvk.Kind, nil
+}
+
+func (h *Handler) existingResourcesExceedLimit(ctx context.Context, _ admission.Request, gvr *metav1.GroupVersionResource, limit int64) (bool, error) {
+ timeoutContext, cancel := context.WithTimeout(ctx, 10*time.Second)
+ defer cancel()
+
+ // Get the proper Kind for this resource
+ kind, err := h.getKindFromGVR(gvr)
+ if err != nil {
+ return false, fmt.Errorf("failed to list resources for calculating object count: %w", err)
+ }
+
+ list := &metav1.PartialObjectMetadataList{}
+ list.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: gvr.Group,
+ Version: gvr.Version,
+ Kind: kind + "List",
+ })
+ // List all resources of this type cluster-wide (since we only count non-namespaced resources)
+ if err := h.APIReader.List(timeoutContext, list, client.Limit(limit+1)); err != nil {
+ return false, fmt.Errorf("failed to list resources for counting: %v", err)
+ }
+
+ return int64(len(list.Items)) >= limit, nil
}
diff --git a/pkg/admissioncontroller/webhook/admission/resourcesize/handler_test.go b/pkg/admissioncontroller/webhook/admission/resourcesize/handler_test.go
index 2e59deee47c..f4ae7ce799b 100644
--- a/pkg/admissioncontroller/webhook/admission/resourcesize/handler_test.go
+++ b/pkg/admissioncontroller/webhook/admission/resourcesize/handler_test.go
@@ -22,15 +22,18 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apiserver/pkg/authentication/serviceaccount"
"sigs.k8s.io/controller-runtime/pkg/client"
+ fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
logzap "sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
admissioncontrollerconfigv1alpha1 "github.com/gardener/gardener/pkg/admissioncontroller/apis/config/v1alpha1"
. "github.com/gardener/gardener/pkg/admissioncontroller/webhook/admission/resourcesize"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/client/kubernetes"
"github.com/gardener/gardener/pkg/logger"
)
@@ -45,12 +48,13 @@ var _ = Describe("handler", func() {
logBuffer *gbytes.Buffer
testEncoder runtime.Encoder
- projectsSizeLimit, _ = resource.ParseQuantity("0M")
- secretSizeLimit, _ = resource.ParseQuantity("1Mi")
+ seedCountLimit = int64(0)
+ projectsSizeLimit = resource.MustParse("0M")
+ secretSizeLimit = resource.MustParse("1Mi")
// size of shoot w/ namespace, name, w/o spec
- shootsv1beta1SizeLimit, _ = resource.ParseQuantity("342")
+ shootsv1beta1SizeLimit = resource.MustParse("342")
// size of shoot w/ namespace, name, w/o spec -1 byte
- shootsv1alpha1SizeLimit, _ = resource.ParseQuantity("342")
+ shootsv1alpha1SizeLimit = resource.MustParse("342")
restrictedUserName = "restrictedUser"
unrestrictedUserName = "unrestrictedUser"
@@ -82,25 +86,31 @@ var _ = Describe("handler", func() {
APIGroups: []string{"*"},
APIVersions: []string{"*"},
Resources: []string{"projects"},
- Size: projectsSizeLimit,
+ Size: &projectsSizeLimit,
},
{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"secrets"},
- Size: secretSizeLimit,
+ Size: &secretSizeLimit,
},
{
APIGroups: []string{"core.gardener.cloud"},
APIVersions: []string{"v1beta1"},
Resources: []string{"shoots"},
- Size: shootsv1beta1SizeLimit,
+ Size: &shootsv1beta1SizeLimit,
},
{
APIGroups: []string{"core.gardener.cloud"},
APIVersions: []string{"v1alpha1"},
Resources: []string{"shoots"},
- Size: shootsv1alpha1SizeLimit,
+ Size: &shootsv1alpha1SizeLimit,
+ },
+ {
+ APIGroups: []string{"core.gardener.cloud"},
+ APIVersions: []string{"v1beta1"},
+ Resources: []string{"seeds"},
+ Count: &seedCountLimit,
},
},
}
@@ -153,6 +163,18 @@ var _ = Describe("handler", func() {
}
}
+ seed = func() runtime.Object {
+ return &gardencorev1beta1.Seed{
+ TypeMeta: metav1.TypeMeta{
+ Kind: "Seed",
+ APIVersion: gardencorev1beta1.SchemeGroupVersion.String(),
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-seed",
+ },
+ }
+ }
+
unrestrictedUser = func() authenticationv1.UserInfo {
return authenticationv1.UserInfo{
Username: unrestrictedUserName,
@@ -193,14 +215,34 @@ var _ = Describe("handler", func() {
logBuffer = gbytes.NewBuffer()
log = logger.MustNewZapLogger(logger.DebugLevel, logger.FormatJSON, logzap.WriteTo(io.MultiWriter(GinkgoWriter, logBuffer)), logzap.Level(zapcore.Level(0)))
- handler = &Handler{Logger: log, Config: config()}
+ // Create a REST mapper that includes Gardener resources
+ restMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{
+ corev1.SchemeGroupVersion,
+ gardencorev1beta1.SchemeGroupVersion,
+ })
+
+ // Add Seed resource mappings
+ restMapper.Add(schema.GroupVersionKind{
+ Group: "core.gardener.cloud",
+ Version: "v1beta1",
+ Kind: "Seed",
+ }, meta.RESTScopeRoot)
+
+ fakeClient := fakeclient.NewClientBuilder().WithScheme(kubernetes.GardenScheme).WithRESTMapper(restMapper).Build()
+ handler = &Handler{
+ Logger: log,
+ Config: config(),
+ APIReader: fakeClient,
+ RESTMapper: fakeClient.RESTMapper(),
+ }
testEncoder = &json.Serializer{}
request = admission.Request{}
- request.Operation = admissionv1.Update
})
- test := func(objFn func() runtime.Object, userFn func() authenticationv1.UserInfo, expectedAllowed bool) {
+ test := func(objFn func() runtime.Object, userFn func() authenticationv1.UserInfo, requestOperation admissionv1.Operation, expectedAllowed bool) {
+ request.Operation = requestOperation
+
if obj := objFn(); obj != nil {
objData, err := runtime.Encode(testEncoder, obj)
Expect(err).NotTo(HaveOccurred())
@@ -237,12 +279,12 @@ var _ = Describe("handler", func() {
Context("ignored requests", func() {
It("empty resource", func() {
- test(empty, restrictedUser, true)
+ test(empty, restrictedUser, admissionv1.Update, true)
})
})
It("should pass because size is in range for v1beta1 shoot", func() {
- test(shootv1beta1, restrictedUser, true)
+ test(shootv1beta1, restrictedUser, admissionv1.Update, true)
})
It("should pass because size is in range for v1beta1 shoot without considering status", func() {
@@ -267,7 +309,7 @@ var _ = Describe("handler", func() {
Expect(shootsv1beta1SizeLimit.CmpInt64(int64(len(objData)))).Should(Equal(-1))
return shootWithLargeStatus
}
- test(largeShoot, restrictedUser, true)
+ test(largeShoot, restrictedUser, admissionv1.Update, true)
})
It("should pass because size is in range for v1beta1 shoot without considering managed fields", func() {
@@ -289,42 +331,50 @@ var _ = Describe("handler", func() {
return shootWithLargeStatus
}
- test(largeShoot, restrictedUser, true)
+ test(largeShoot, restrictedUser, admissionv1.Update, true)
})
It("should pass because of unrestricted user", func() {
- test(shootv1beta1, unrestrictedUser, true)
+ test(shootv1beta1, unrestrictedUser, admissionv1.Update, true)
})
It("should pass because of unrestricted group", func() {
- test(shootv1beta1, unrestrictedGroup, true)
+ test(shootv1beta1, unrestrictedGroup, admissionv1.Update, true)
})
It("should pass because size is in range for secret", func() {
- test(secret, restrictedUser, true)
+ test(secret, restrictedUser, admissionv1.Update, true)
})
It("should pass because no limits configured for configMaps", func() {
- test(configMap, restrictedUser, true)
+ test(configMap, restrictedUser, admissionv1.Update, true)
})
It("should fail because size is not in range for project", func() {
- test(project, restrictedUser, false)
+ test(project, restrictedUser, admissionv1.Update, false)
})
It("should pass because of unrestricted user", func() {
- test(project, unrestrictedUser, true)
+ test(project, unrestrictedUser, admissionv1.Update, true)
})
It("should pass because of unrestricted group", func() {
- test(project, unrestrictedGroup, true)
+ test(project, unrestrictedGroup, admissionv1.Update, true)
})
It("should pass because of unrestricted service account", func() {
- test(project, unrestrictedServiceAccount, true)
+ test(project, unrestrictedServiceAccount, admissionv1.Update, true)
})
It("should fail because of restricted service account", func() {
- test(project, restrictedServiceAccount, false)
+ test(project, restrictedServiceAccount, admissionv1.Update, false)
+ })
+
+ It("should fail because of count limit of seeds", func() {
+ test(seed, restrictedUser, admissionv1.Create, false)
+ })
+
+ It("should pass seed creation despite count limit being reached when user has unrestricted privileges", func() {
+ test(seed, unrestrictedServiceAccount, admissionv1.Create, true)
})
})
diff --git a/pkg/apis/operator/v1alpha1/conversion/conversion.go b/pkg/apis/operator/v1alpha1/conversion/conversion.go
index 7485e8085c2..9b0fe2f05b3 100644
--- a/pkg/apis/operator/v1alpha1/conversion/conversion.go
+++ b/pkg/apis/operator/v1alpha1/conversion/conversion.go
@@ -32,6 +32,7 @@ func ConvertToAdmissionControllerResourceAdmissionConfiguration(config *operator
APIVersions: limit.APIVersions,
Resources: limit.Resources,
Size: limit.Size,
+ Count: limit.Count,
})
}
diff --git a/pkg/apis/operator/v1alpha1/conversion/conversion_test.go b/pkg/apis/operator/v1alpha1/conversion/conversion_test.go
index eacf95c7330..b2af636e255 100644
--- a/pkg/apis/operator/v1alpha1/conversion/conversion_test.go
+++ b/pkg/apis/operator/v1alpha1/conversion/conversion_test.go
@@ -12,6 +12,7 @@ import (
. "github.com/onsi/gomega/gstruct"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/resource"
+ "k8s.io/utils/ptr"
admissioncontrollerconfigv1alpha1 "github.com/gardener/gardener/pkg/admissioncontroller/apis/config/v1alpha1"
operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1"
@@ -33,13 +34,13 @@ var _ = Describe("conversion", func() {
APIVersions: []string{"v1beta1"},
APIGroups: []string{"core.gardener.cloud"},
Resources: []string{"shoots"},
- Size: resource.MustParse("1Ki"),
+ Size: ptr.To(resource.MustParse("1Ki")),
},
{
APIVersions: []string{"v1"},
APIGroups: []string{""},
Resources: []string{"secrets", "configmaps"},
- Size: resource.MustParse("100Ki"),
+ Size: ptr.To(resource.MustParse("100Ki")),
},
},
UnrestrictedSubjects: []rbacv1.Subject{},
diff --git a/pkg/apis/operator/v1alpha1/types_garden.go b/pkg/apis/operator/v1alpha1/types_garden.go
index d9bb48d72bf..bb90a3b81ac 100644
--- a/pkg/apis/operator/v1alpha1/types_garden.go
+++ b/pkg/apis/operator/v1alpha1/types_garden.go
@@ -568,7 +568,11 @@ type ResourceLimit struct {
// Resources is the name of the resource this rule applies to. WildcardAll represents all resources.
Resources []string `json:"resources"`
// Size specifies the imposed limit.
- Size resource.Quantity `json:"size"`
+ // +optional
+ Size *resource.Quantity `json:"size"`
+ // Count specifies the maximum number of resources of the given kind. Only cluster-scoped resources are considered.
+ // +optional
+ Count *int64 `json:"count,omitempty"`
}
// GardenerControllerManagerConfig contains configuration settings for the gardener-controller-manager.
diff --git a/pkg/apis/operator/v1alpha1/validation/garden_test.go b/pkg/apis/operator/v1alpha1/validation/garden_test.go
index db8961eda02..8ff23745eb2 100644
--- a/pkg/apis/operator/v1alpha1/validation/garden_test.go
+++ b/pkg/apis/operator/v1alpha1/validation/garden_test.go
@@ -2130,7 +2130,7 @@ var _ = Describe("Validation Tests", func() {
APIGroups: apiGroups,
APIVersions: versions,
Resources: resources,
- Size: s,
+ Size: ptr.To(s),
},
},
},
diff --git a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
index 0dca64a1877..df655a86277 100644
--- a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
@@ -1465,7 +1465,16 @@ func (in *ResourceLimit) DeepCopyInto(out *ResourceLimit) {
*out = make([]string, len(*in))
copy(*out, *in)
}
- out.Size = in.Size.DeepCopy()
+ if in.Size != nil {
+ in, out := &in.Size, &out.Size
+ x := (*in).DeepCopy()
+ *out = &x
+ }
+ if in.Count != nil {
+ in, out := &in.Count, &out.Count
+ *out = new(int64)
+ **out = **in
+ }
return
}
diff --git a/pkg/component/gardener/admissioncontroller/admission_controller_test.go b/pkg/component/gardener/admissioncontroller/admission_controller_test.go
index 6d7fe49904c..c593d8f9392 100644
--- a/pkg/component/gardener/admissioncontroller/admission_controller_test.go
+++ b/pkg/component/gardener/admissioncontroller/admission_controller_test.go
@@ -103,13 +103,13 @@ var _ = Describe("GardenerAdmissionController", func() {
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"secrets", "configmaps"},
- Size: resource.MustParse("1Mi"),
+ Size: ptr.To(resource.MustParse("1Mi")),
},
{
APIGroups: []string{"core.gardener.cloud"},
APIVersions: []string{"v1beta1"},
Resources: []string{"shoots"},
- Size: resource.MustParse("100Ki"),
+ Size: ptr.To(resource.MustParse("100Ki")),
},
},
UnrestrictedSubjects: []rbacv1.Subject{{
From 4ac95434a77ee6798969ebea0cdc970a9ebe3c2e Mon Sep 17 00:00:00 2001
From: Niki Dokovski
Date: Wed, 5 Nov 2025 16:39:28 +0100
Subject: [PATCH 044/176] Update logging stack (#13358)
* fluent-bit: bump up fluent-bit to 4.1.1
* logging: bump up fluent-bit plugin to v0.68.0
---
imagevector/containers.yaml | 12 ++++++------
.../observability/logging/fluentbit/fluentbit.go | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index eb2bd901913..4d2cb5a9054 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -577,7 +577,7 @@ images:
- name: fluent-bit
sourceRepository: github.com/fluent/fluent-operator
repository: europe-docker.pkg.dev/gardener-project/releases/3rd/fluent-operator/fluent-bit
- tag: "v4.0.9"
+ tag: "v4.1.1"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
@@ -596,7 +596,7 @@ images:
name: fluent-bit-to-vali
sourceRepository: github.com/gardener/logging
repository: europe-docker.pkg.dev/gardener-project/releases/gardener/fluent-bit-to-vali
- tag: "v0.67.0"
+ tag: "v0.68.0"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
@@ -631,7 +631,7 @@ images:
- name: vali-curator
sourceRepository: github.com/gardener/logging
repository: europe-docker.pkg.dev/gardener-project/releases/gardener/vali-curator
- tag: "v0.67.0"
+ tag: "v0.68.0"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
@@ -687,7 +687,7 @@ images:
name: telegraf-iptables
sourceRepository: github.com/gardener/logging
repository: europe-docker.pkg.dev/gardener-project/releases/gardener/telegraf-iptables
- tag: "v0.67.0"
+ tag: "v0.68.0"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
@@ -707,7 +707,7 @@ images:
- name: event-logger
sourceRepository: github.com/gardener/logging
repository: europe-docker.pkg.dev/gardener-project/releases/gardener/event-logger
- tag: "v0.67.0"
+ tag: "v0.68.0"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
@@ -724,7 +724,7 @@ images:
- name: tune2fs
sourceRepository: github.com/gardener/logging
repository: europe-docker.pkg.dev/gardener-project/releases/gardener/tune2fs
- tag: "v0.67.0"
+ tag: "v0.68.0"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
diff --git a/pkg/component/observability/logging/fluentbit/fluentbit.go b/pkg/component/observability/logging/fluentbit/fluentbit.go
index c59893a430a..00d86826d76 100644
--- a/pkg/component/observability/logging/fluentbit/fluentbit.go
+++ b/pkg/component/observability/logging/fluentbit/fluentbit.go
@@ -367,7 +367,7 @@ func (f *fluentBit) getFluentBit() *fluentbitv1alpha2.FluentBit {
Command: []string{
"/fluent-bit/bin/fluent-bit-watcher",
"-e",
- "/fluent-bit/plugins/out_vali.so",
+ "/fluent-bit/plugins/output_plugin.so",
"-c",
"/fluent-bit/config/fluent-bit.conf",
},
From 2d3c9d9ce5d1fe84737eebc8fb41d04ff8ebdeda Mon Sep 17 00:00:00 2001
From: rhubenov
Date: Wed, 5 Nov 2025 20:00:19 +0200
Subject: [PATCH 045/176] Worker pool rollout v2 (#12829)
* Add new status field to internal and external Shoot API
Co-authored-by: Jeremy Rickards
Co-authored-by: Gerrit Schwerthelm
* Validate annotation
Co-authored-by: Jeremy Rickards
Co-authored-by: Gerrit Schwerthel
* Add logic for increasing generation & not removing the operation in gardenapi
Co-authored-by: Jeremy Rickards
Co-authored-by: Gerrit Schwerthelm
* Update pending workers in shoot status & attach annotation to machinedeployments
Co-authored-by: Gerrit Schwerthelm
Co-authored-by: Jeremy Rickards
* Make sure annotation is not removed by mcm
Co-authored-by: Jeremy Rickards
Co-authored-by: Gerrit Schwerthelm
* Add e2e test for the annotation
Co-authored-by: Gerrit Schwerthelm
Co-authored-by: Jeremy Rickards
* Add documentation
Co-authored-by: Gerrit Schwerthelm
Co-authored-by: Jeremy Rickards
* Make generate
Co-authored-by: Gerrit Schwerthelm
Co-authored-by: Jeremy Rickards
* Review changes
* Forbid annotation for shoots with inplace update enabled
* Review changes (docs + formatting)
* Include warning for the `InPlace` update strategies in docs
* Add tests for forbidding annotation on `Shoot` clusters with `InPlace` strategy
* Note highlight & fix note for forbidding worker pools rather than `Shoots`
---------
Co-authored-by: Jeremy Rickards
Co-authored-by: Gerrit Schwerthelm
---
.../operator/templates/crd-gardens.yaml | 16 +-
docs/README.md | 1 +
docs/api-reference/core.md | 53 +-
.../dual-stack-networking-migration.md | 6 +
.../worker_pool_manual_rollout.md | 29 +
...0-crd-operator.gardener.cloud_gardens.yaml | 16 +-
.../genericactuator/actuator_reconcile.go | 6 +
pkg/apis/core/types_shoot.go | 13 +-
.../core/v1beta1/constants/types_constants.go | 3 +
pkg/apis/core/v1beta1/generated.pb.go | 2237 +++++++++--------
pkg/apis/core/v1beta1/generated.proto | 16 +-
pkg/apis/core/v1beta1/helper/shoot.go | 14 +
pkg/apis/core/v1beta1/helper/shoot_test.go | 28 +
pkg/apis/core/v1beta1/types_shoot.go | 15 +-
.../core/v1beta1/zz_generated.conversion.go | 32 +
.../core/v1beta1/zz_generated.deepcopy.go | 28 +
pkg/apis/core/validation/shoot.go | 52 +-
pkg/apis/core/validation/shoot_test.go | 141 ++
pkg/apis/core/zz_generated.deepcopy.go | 28 +
pkg/apiserver/openapi/api_violations.report | 1 +
pkg/apiserver/openapi/openapi_generated.go | 42 +-
pkg/apiserver/registry/core/shoot/strategy.go | 5 +-
.../controller/shoot/shoot/reconciler.go | 71 +-
.../controller/shoot/shoot/reconciler_test.go | 20 +
.../gardener/shoot/create_rotate_delete.go | 78 +-
25 files changed, 1905 insertions(+), 1046 deletions(-)
create mode 100644 docs/usage/shoot-operations/worker_pool_manual_rollout.md
diff --git a/charts/gardener/operator/templates/crd-gardens.yaml b/charts/gardener/operator/templates/crd-gardens.yaml
index 7d31146cc7c..3d85255cfbe 100644
--- a/charts/gardener/operator/templates/crd-gardens.yaml
+++ b/charts/gardener/operator/templates/crd-gardens.yaml
@@ -2053,13 +2053,13 @@ spec:
PendingWorkersRollouts contains the name of a worker pool and the initiation time of their last rollout due to
credentials rotation.
items:
- description: |-
- PendingWorkersRollout contains the name of a worker pool and the initiation time of their last rollout due to
- credentials rotation.
+ description: PendingWorkersRollout contains the name
+ of a worker pool and the initiation time of their
+ last rollout.
properties:
lastInitiationTime:
description: LastInitiationTime is the most recent
- time when the credential rotation was initiated.
+ time when the worker rollout was initiated.
format: date-time
type: string
name:
@@ -2169,13 +2169,13 @@ spec:
PendingWorkersRollouts contains the name of a worker pool and the initiation time of their last rollout due to
credentials rotation.
items:
- description: |-
- PendingWorkersRollout contains the name of a worker pool and the initiation time of their last rollout due to
- credentials rotation.
+ description: PendingWorkersRollout contains the name
+ of a worker pool and the initiation time of their
+ last rollout.
properties:
lastInitiationTime:
description: LastInitiationTime is the most recent
- time when the credential rotation was initiated.
+ time when the worker rollout was initiated.
format: date-time
type: string
name:
diff --git a/docs/README.md b/docs/README.md
index ce088f725dd..cf916537e95 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -62,6 +62,7 @@
* [Supported Kubernetes versions](usage/shoot-operations/supported_k8s_versions.md)
* [Controlling the Kubernetes versions for specific worker pools](usage/shoot-operations/worker_pool_k8s_versions.md)
* [Migration from SecretBinding to CredentialsBinding](usage/shoot-operations/secretbinding-to-credentialsbinding-migration.md)
+* [Manual Worker Pool Rollout](usage/shoot-operations/worker_pool_manual_rollout.md)
### High Availability
diff --git a/docs/api-reference/core.md b/docs/api-reference/core.md
index 370dddc5ad2..9e07bec8a6d 100644
--- a/docs/api-reference/core.md
+++ b/docs/api-reference/core.md
@@ -8976,6 +8976,39 @@ If not present, the value will be computed based on the “Begin” valu
+
ManualWorkerPoolRollout contains information about the worker pool rollout progress that has been initiated via the gardener.cloud/operation=rollout-workers annotation.
Class configures the Service.spec.loadBalancerClass field for the load balancer services on the seed.
+Note that changing the loadBalancerClass of existing LoadBalancer services is denied by Kubernetes.
+
+
SeedSettingLoadBalancerServicesZonalIngress
diff --git a/docs/operations/seed_settings.md b/docs/operations/seed_settings.md
index 62e016d1912..234442ccc36 100644
--- a/docs/operations/seed_settings.md
+++ b/docs/operations/seed_settings.md
@@ -72,6 +72,13 @@ In most cases, the cloud-controller-manager (responsible for managing these load
By setting the `.spec.settings.loadBalancerServices.annotations` field the Gardener administrator can specify a list of annotations, which will be injected into the `Service`s of type `LoadBalancer`.
+### Load Balancer Class
+
+By default, Gardener creates `Services` without the `spec.loadBalancerClass` field set, meaning that the default load balancer implementation of the underlying cloud infrastructure is used (implemented by the `Service` controller of cloud-controller-manager).
+If a non-default load balancer implementation should be used for load balancer services in the seed cluster, the `spec.settings.loadBalancerServices.loadBalancerClass` field can be configured accordingly to set the `spec.loadBalancerClass` on the created `Service` objects.
+Note that changing the `loadBalancerClass` of existing load balancer services is denied by Kubernetes, i.e., this setting can only be applied automatically to newly created load balancer services.
+If an existing load balancer service should use a different load balancer class, the migration needs to be performed manually by the operator.
+
### External Traffic Policy
Setting the [external traffic policy](https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip) to `Local` can be beneficial as it
diff --git a/docs/usage/networking/exposureclasses.md b/docs/usage/networking/exposureclasses.md
index 03ede51d83c..c00e49c49f9 100644
--- a/docs/usage/networking/exposureclasses.md
+++ b/docs/usage/networking/exposureclasses.md
@@ -128,6 +128,7 @@ exposureClassHandlers:
loadbalancer/network: internet
- name: internal-config
loadBalancerService:
+ class: internal-loadbalancer
annotations:
loadbalancer/network: internal
sni:
@@ -146,6 +147,11 @@ The load balancer service needs to be configured in a way that it is reachable f
Therefore, the configuration of load balancer service need to be specified, which can be done via the `.loadBalancerService` section.
The common way to influence load balancer service behaviour is via annotations where the respective cloud-controller-manager will react on and configure the infrastructure load balancer accordingly.
+To select a non-default load balancer implementation, the `class` field can be set to configure the `spec.loadBalancerClass` on the created `Service` objects.
+If the `class` field is unset, `spec.loadBalancerClass` is not configured and the default load balancer implementation of the underlying cloud infrastructure is used (implemented by the `Service` controller of cloud-controller-manager).
+Note that changing the `loadBalancerClass` of existing load balancer services is denied by Kubernetes, i.e., this setting can only be applied automatically to newly created load balancer services.
+If an existing load balancer service should use a different load balancer class, the migration needs to be performed manually by the operator.
+
The control planes on a `Seed` will be exposed via a central load balancer and with Envoy via TLS SNI passthrough proxy.
In this case, the gardenlet will install a dedicated ingress gateway (Envoy + load balancer + respective configuration) for each handler on the `Seed`.
The configuration of the ingress gateways can be controlled via the `.sni` section in the same way like for the default ingress gateways.
diff --git a/example/50-seed.yaml b/example/50-seed.yaml
index 3e10a09c632..fdc699bc284 100644
--- a/example/50-seed.yaml
+++ b/example/50-seed.yaml
@@ -93,6 +93,7 @@ spec:
# loadBalancerServices:
# annotations:
# foo: bar
+ # class: non-default-load-balancer-class
# externalTrafficPolicy: Local
# proxyProtocol:
# allowed: true
diff --git a/pkg/apis/core/types_seed.go b/pkg/apis/core/types_seed.go
index e647cbe2296..7b634a3b458 100644
--- a/pkg/apis/core/types_seed.go
+++ b/pkg/apis/core/types_seed.go
@@ -267,6 +267,9 @@ type SeedSettingLoadBalancerServices struct {
// ZonalIngress controls whether ingress gateways are deployed per availability zone.
// Defaults to true.
ZonalIngress *SeedSettingLoadBalancerServicesZonalIngress
+ // Class configures the Service.spec.loadBalancerClass field for the load balancer services on the seed.
+ // Note that changing the loadBalancerClass of existing LoadBalancer services is denied by Kubernetes.
+ Class *string
}
// SeedSettingLoadBalancerServicesZones controls settings, which are specific to the single-zone load balancers in a
diff --git a/pkg/apis/core/v1beta1/generated.pb.go b/pkg/apis/core/v1beta1/generated.pb.go
index 849860f37b9..3da202d663a 100644
--- a/pkg/apis/core/v1beta1/generated.pb.go
+++ b/pkg/apis/core/v1beta1/generated.pb.go
@@ -5969,926 +5969,927 @@ func init() {
}
var fileDescriptor_ca37af0df9a5bbd2 = []byte{
- // 14698 bytes of a gzipped FileDescriptorProto
+ // 14705 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6b, 0x70, 0x24, 0xd9,
0x55, 0x20, 0xec, 0x2c, 0xbd, 0x8f, 0x1e, 0x2d, 0xdd, 0x56, 0x77, 0xab, 0xd5, 0x8f, 0x6a, 0xe7,
0x8c, 0x4d, 0x0f, 0x63, 0xab, 0x99, 0xf1, 0xd8, 0xe3, 0x19, 0x33, 0x0f, 0xa9, 0x4a, 0xea, 0x2e,
0xb7, 0xa4, 0xae, 0xb9, 0x25, 0xcd, 0x8c, 0x67, 0x60, 0x4c, 0x2a, 0xeb, 0xaa, 0x94, 0xd3, 0x59,
0x99, 0x35, 0x99, 0x59, 0x6a, 0xa9, 0xc7, 0xc6, 0x0f, 0x30, 0x9f, 0x6d, 0x0c, 0x1f, 0xf0, 0x01,
- 0xfe, 0x6c, 0xb3, 0xc1, 0x60, 0x02, 0xb3, 0xbb, 0xb0, 0x66, 0x03, 0x82, 0x8d, 0x00, 0x02, 0x76,
- 0x21, 0x82, 0xc5, 0x10, 0x40, 0x10, 0x18, 0x76, 0xcd, 0x02, 0x02, 0x6b, 0xbd, 0xb0, 0x11, 0xfb,
- 0x8c, 0x25, 0x62, 0x89, 0xe8, 0x25, 0xd8, 0x8d, 0xfb, 0xc8, 0xcc, 0x9b, 0xaf, 0x52, 0x29, 0x4b,
- 0x92, 0x67, 0x16, 0xff, 0x92, 0xea, 0x9e, 0x7b, 0xcf, 0xb9, 0xaf, 0x3c, 0xf7, 0x9c, 0x73, 0xcf,
- 0x3d, 0x07, 0x16, 0x1a, 0x86, 0xb7, 0xd5, 0xde, 0x98, 0xd3, 0xed, 0xe6, 0xb5, 0x86, 0xe6, 0xd4,
- 0x89, 0x45, 0x9c, 0xf0, 0x9f, 0xd6, 0xed, 0xc6, 0x35, 0xad, 0x65, 0xb8, 0xd7, 0x74, 0xdb, 0x21,
- 0xd7, 0xb6, 0x1f, 0xda, 0x20, 0x9e, 0xf6, 0xd0, 0xb5, 0x06, 0x85, 0x69, 0x1e, 0xa9, 0xcf, 0xb5,
- 0x1c, 0xdb, 0xb3, 0xd1, 0xc3, 0x21, 0x8e, 0x39, 0xbf, 0x69, 0xf8, 0x4f, 0xeb, 0x76, 0x63, 0x8e,
- 0xe2, 0x98, 0xa3, 0x38, 0xe6, 0x04, 0x8e, 0xd9, 0xb7, 0xcb, 0x74, 0xed, 0x86, 0x7d, 0x8d, 0xa1,
- 0xda, 0x68, 0x6f, 0xb2, 0x5f, 0xec, 0x07, 0xfb, 0x8f, 0x93, 0x98, 0x7d, 0xe0, 0xf6, 0xbb, 0xdd,
- 0x39, 0xc3, 0xa6, 0x9d, 0xb9, 0xa6, 0xb5, 0x3d, 0xdb, 0xd5, 0x35, 0xd3, 0xb0, 0x1a, 0xd7, 0xb6,
- 0x13, 0xbd, 0x99, 0x55, 0xa5, 0xaa, 0xa2, 0xdb, 0x1d, 0xeb, 0x38, 0x1b, 0x9a, 0x9e, 0x56, 0xe7,
- 0x46, 0x58, 0x87, 0xec, 0x78, 0xc4, 0x72, 0x0d, 0xdb, 0x72, 0xdf, 0x4e, 0x47, 0x42, 0x9c, 0x6d,
- 0x79, 0x6e, 0x22, 0x15, 0xd2, 0x30, 0x3d, 0x12, 0x62, 0x6a, 0x6a, 0xfa, 0x96, 0x61, 0x11, 0x67,
- 0xd7, 0x6f, 0x7e, 0xcd, 0x21, 0xae, 0xdd, 0x76, 0x74, 0x72, 0xa8, 0x56, 0xee, 0xb5, 0x26, 0xf1,
- 0xb4, 0x34, 0x5a, 0xd7, 0xb2, 0x5a, 0x39, 0x6d, 0xcb, 0x33, 0x9a, 0x49, 0x32, 0xef, 0x3a, 0xa8,
- 0x81, 0xab, 0x6f, 0x91, 0xa6, 0x96, 0x68, 0xf7, 0x8e, 0xac, 0x76, 0x6d, 0xcf, 0x30, 0xaf, 0x19,
- 0x96, 0xe7, 0x7a, 0x4e, 0xbc, 0x91, 0xfa, 0x49, 0x05, 0x26, 0xe7, 0xab, 0x95, 0x1a, 0x9b, 0xc1,
- 0x65, 0xbb, 0xd1, 0x30, 0xac, 0x06, 0x7a, 0x10, 0x46, 0xb6, 0x89, 0xb3, 0x61, 0xbb, 0x86, 0xb7,
- 0x3b, 0xa3, 0x5c, 0x51, 0xae, 0x0e, 0x2c, 0x8c, 0xef, 0xef, 0x15, 0x47, 0x9e, 0xf5, 0x0b, 0x71,
- 0x08, 0x47, 0x15, 0x38, 0xbd, 0xe5, 0x79, 0xad, 0x79, 0x5d, 0x27, 0xae, 0x1b, 0xd4, 0x98, 0x29,
- 0xb0, 0x66, 0xe7, 0xf6, 0xf7, 0x8a, 0xa7, 0x6f, 0xac, 0xad, 0x55, 0x63, 0x60, 0x9c, 0xd6, 0x46,
- 0xfd, 0x79, 0x05, 0xa6, 0x82, 0xce, 0x60, 0xf2, 0x4a, 0x9b, 0xb8, 0x9e, 0x8b, 0x30, 0x9c, 0x6d,
- 0x6a, 0x3b, 0xab, 0xb6, 0xb5, 0xd2, 0xf6, 0x34, 0xcf, 0xb0, 0x1a, 0x15, 0x6b, 0xd3, 0x34, 0x1a,
- 0x5b, 0x9e, 0xe8, 0xda, 0xec, 0xfe, 0x5e, 0xf1, 0xec, 0x4a, 0x6a, 0x0d, 0x9c, 0xd1, 0x92, 0x76,
- 0xba, 0xa9, 0xed, 0x24, 0x10, 0x4a, 0x9d, 0x5e, 0x49, 0x82, 0x71, 0x5a, 0x1b, 0xf5, 0x9d, 0x30,
- 0xc5, 0xc7, 0x81, 0x89, 0xeb, 0x39, 0x86, 0xee, 0x19, 0xb6, 0x85, 0xae, 0x40, 0xbf, 0xa5, 0x35,
- 0x09, 0xeb, 0xe1, 0xc8, 0xc2, 0xd8, 0x97, 0xf6, 0x8a, 0x6f, 0xda, 0xdf, 0x2b, 0xf6, 0xaf, 0x6a,
- 0x4d, 0x82, 0x19, 0x44, 0xfd, 0x9f, 0x05, 0xb8, 0x98, 0x68, 0xf7, 0x9c, 0xe1, 0x6d, 0xdd, 0x6a,
- 0xd1, 0xff, 0x5c, 0xf4, 0xfd, 0x0a, 0x4c, 0x69, 0xf1, 0x0a, 0x0c, 0xe1, 0xe8, 0xc3, 0x8b, 0x73,
- 0x87, 0xff, 0xc0, 0xe7, 0x12, 0xd4, 0x16, 0xce, 0x8b, 0x7e, 0x25, 0x07, 0x80, 0x93, 0xa4, 0xd1,
- 0xc7, 0x15, 0x18, 0xb2, 0x79, 0xe7, 0x66, 0x0a, 0x57, 0xfa, 0xae, 0x8e, 0x3e, 0xfc, 0xed, 0x47,
- 0xd2, 0x0d, 0x69, 0xd0, 0x73, 0xe2, 0xef, 0xa2, 0xe5, 0x39, 0xbb, 0x0b, 0xa7, 0x44, 0xf7, 0x86,
- 0x44, 0x29, 0xf6, 0xc9, 0xcf, 0x3e, 0x0e, 0x63, 0x72, 0x4d, 0x34, 0x09, 0x7d, 0xb7, 0x09, 0xdf,
- 0xaa, 0x23, 0x98, 0xfe, 0x8b, 0xa6, 0x61, 0x60, 0x5b, 0x33, 0xdb, 0x84, 0x2d, 0xe9, 0x08, 0xe6,
- 0x3f, 0x1e, 0x2f, 0xbc, 0x5b, 0x51, 0x1f, 0x86, 0x81, 0xf9, 0x7a, 0xdd, 0xb6, 0xd0, 0x03, 0x30,
- 0x44, 0x2c, 0x6d, 0xc3, 0x24, 0x75, 0xd6, 0x70, 0x38, 0xa4, 0xb7, 0xc8, 0x8b, 0xb1, 0x0f, 0x57,
- 0x7f, 0xa4, 0x00, 0x83, 0xac, 0x91, 0x8b, 0x7e, 0x48, 0x81, 0xd3, 0xb7, 0xdb, 0x1b, 0xc4, 0xb1,
- 0x88, 0x47, 0xdc, 0xb2, 0xe6, 0x6e, 0x6d, 0xd8, 0x9a, 0x53, 0x17, 0x0b, 0x73, 0x3d, 0xcf, 0x8c,
- 0xdc, 0x4c, 0xa2, 0xe3, 0x7b, 0x30, 0x05, 0x80, 0xd3, 0x88, 0xa3, 0x6d, 0x18, 0xb3, 0x1a, 0x86,
- 0xb5, 0x53, 0xb1, 0x1a, 0x0e, 0x71, 0x5d, 0x36, 0xe8, 0xd1, 0x87, 0x9f, 0xce, 0xd3, 0x99, 0x55,
- 0x09, 0xcf, 0xc2, 0xe4, 0xfe, 0x5e, 0x71, 0x4c, 0x2e, 0xc1, 0x11, 0x3a, 0xea, 0xdf, 0x2b, 0x70,
- 0x6a, 0xbe, 0xde, 0x34, 0x5c, 0xca, 0x69, 0xab, 0x66, 0xbb, 0x61, 0x74, 0xb1, 0xf5, 0xd1, 0x33,
- 0x30, 0xa8, 0xdb, 0xd6, 0xa6, 0xd1, 0x10, 0xfd, 0x7c, 0xfb, 0x1c, 0xe7, 0x5c, 0x73, 0x32, 0xe7,
- 0x62, 0xdd, 0x13, 0x1c, 0x6f, 0x0e, 0x6b, 0x77, 0x16, 0x7d, 0x86, 0xbe, 0x00, 0xfb, 0x7b, 0xc5,
- 0xc1, 0x12, 0x43, 0x80, 0x05, 0x22, 0x74, 0x15, 0x86, 0xeb, 0x86, 0xcb, 0x17, 0xb3, 0x8f, 0x2d,
- 0xe6, 0xd8, 0xfe, 0x5e, 0x71, 0xb8, 0x2c, 0xca, 0x70, 0x00, 0x45, 0xcb, 0x30, 0x4d, 0x67, 0x90,
- 0xb7, 0xab, 0x11, 0xdd, 0x21, 0x1e, 0xed, 0xda, 0x4c, 0x3f, 0xeb, 0xee, 0xcc, 0xfe, 0x5e, 0x71,
- 0xfa, 0x66, 0x0a, 0x1c, 0xa7, 0xb6, 0x52, 0x97, 0x60, 0x78, 0xde, 0x24, 0x0e, 0x65, 0x08, 0xe8,
- 0x71, 0x98, 0x20, 0x4d, 0xcd, 0x30, 0x31, 0xd1, 0x89, 0xb1, 0x4d, 0x1c, 0x77, 0x46, 0xb9, 0xd2,
- 0x77, 0x75, 0x64, 0x01, 0xed, 0xef, 0x15, 0x27, 0x16, 0x23, 0x10, 0x1c, 0xab, 0xa9, 0x7e, 0x44,
- 0x81, 0xd1, 0xf9, 0x76, 0xdd, 0xf0, 0xf8, 0xb8, 0x90, 0x03, 0xa3, 0x1a, 0xfd, 0x59, 0xb5, 0x4d,
- 0x43, 0xdf, 0x15, 0x9b, 0xeb, 0xa9, 0x5c, 0x9f, 0x5b, 0x88, 0x66, 0xe1, 0xd4, 0xfe, 0x5e, 0x71,
- 0x54, 0x2a, 0xc0, 0x32, 0x11, 0x75, 0x0b, 0x64, 0x18, 0x7a, 0x1f, 0x8c, 0xf1, 0xe1, 0xae, 0x68,
- 0x2d, 0x4c, 0x36, 0x45, 0x1f, 0xee, 0x93, 0xd6, 0xca, 0x27, 0x34, 0x77, 0x6b, 0xe3, 0x65, 0xa2,
- 0x7b, 0x98, 0x6c, 0x12, 0x87, 0x58, 0x3a, 0xe1, 0xdb, 0xa6, 0x24, 0x35, 0xc6, 0x11, 0x54, 0xea,
- 0xff, 0xa7, 0xc0, 0xa5, 0xf9, 0xb6, 0xb7, 0x65, 0x3b, 0xc6, 0x5d, 0xe2, 0x84, 0xd3, 0x1d, 0x60,
- 0x40, 0x4f, 0xc2, 0x84, 0x16, 0x54, 0x58, 0x0d, 0xb7, 0xd3, 0x59, 0xb1, 0x9d, 0x26, 0xe6, 0x23,
- 0x50, 0x1c, 0xab, 0x8d, 0x1e, 0x06, 0x70, 0xc3, 0xb5, 0x65, 0x3c, 0x60, 0x01, 0x89, 0xb6, 0x20,
- 0xad, 0xaa, 0x54, 0x4b, 0xfd, 0x0b, 0x7a, 0x14, 0x6e, 0x6b, 0x86, 0xa9, 0x6d, 0x18, 0xa6, 0xe1,
- 0xed, 0xbe, 0x60, 0x5b, 0xa4, 0x8b, 0xdd, 0xbc, 0x0e, 0xe7, 0xda, 0x96, 0xc6, 0xdb, 0x99, 0x64,
- 0x85, 0xef, 0xdf, 0xb5, 0xdd, 0x16, 0xe1, 0x5c, 0x72, 0x64, 0xe1, 0xc2, 0xfe, 0x5e, 0xf1, 0xdc,
- 0x7a, 0x7a, 0x15, 0x9c, 0xd5, 0x96, 0x9e, 0x7a, 0x12, 0xe8, 0x59, 0xdb, 0x6c, 0x37, 0x05, 0xd6,
- 0x3e, 0x86, 0x95, 0x9d, 0x7a, 0xeb, 0xa9, 0x35, 0x70, 0x46, 0x4b, 0xf5, 0x0b, 0x05, 0x18, 0x5c,
- 0xd0, 0xf4, 0xdb, 0xed, 0x16, 0x7a, 0x1b, 0x0c, 0xb7, 0x1c, 0x7b, 0xdb, 0xa8, 0x13, 0x47, 0x8c,
- 0x6d, 0x52, 0x8c, 0x6d, 0xb8, 0x2a, 0xca, 0x71, 0x50, 0x03, 0x19, 0x30, 0xe1, 0xff, 0x5f, 0xea,
- 0xe1, 0xcb, 0x65, 0x5f, 0x42, 0x35, 0x82, 0x08, 0xc7, 0x10, 0x23, 0x15, 0x06, 0x1d, 0xd2, 0xa0,
- 0x47, 0x5d, 0x1f, 0xeb, 0x16, 0xfb, 0xda, 0x31, 0x2b, 0xc1, 0x02, 0x82, 0xde, 0x0f, 0x13, 0xba,
- 0x43, 0xea, 0xc4, 0xf2, 0x0c, 0xcd, 0x74, 0xe9, 0xe6, 0x1c, 0xe8, 0x7e, 0x73, 0xb2, 0x4e, 0x94,
- 0x22, 0xcd, 0x71, 0x0c, 0x9d, 0xfa, 0xa5, 0x02, 0x8c, 0xf1, 0x89, 0x5a, 0x68, 0xeb, 0xb7, 0x89,
- 0x87, 0xbe, 0x03, 0x86, 0xa9, 0x7c, 0x57, 0xd7, 0x3c, 0x4d, 0x7c, 0x08, 0xdf, 0x92, 0x39, 0x74,
- 0xf6, 0x0d, 0xd2, 0xda, 0x21, 0xf5, 0x15, 0xe2, 0x69, 0xe1, 0xfe, 0x0b, 0xcb, 0x70, 0x80, 0x15,
- 0x6d, 0x42, 0xbf, 0xdb, 0x22, 0xba, 0x98, 0xd8, 0x72, 0x9e, 0x4f, 0x5d, 0xee, 0x71, 0xad, 0x45,
- 0xf4, 0x70, 0xbb, 0xd2, 0x5f, 0x98, 0xe1, 0x47, 0x16, 0x0c, 0xba, 0x9e, 0xe6, 0xb5, 0x5d, 0x36,
- 0xbf, 0xa3, 0x0f, 0x2f, 0xf5, 0x4c, 0x89, 0x61, 0x5b, 0x98, 0x10, 0xb4, 0x06, 0xf9, 0x6f, 0x2c,
- 0xa8, 0xa8, 0xff, 0x56, 0x81, 0x49, 0xb9, 0xfa, 0xb2, 0xe1, 0x7a, 0xe8, 0xdb, 0x12, 0xd3, 0x39,
- 0xd7, 0xdd, 0x74, 0xd2, 0xd6, 0x6c, 0x32, 0x83, 0xdd, 0xea, 0x97, 0x48, 0x53, 0x49, 0x60, 0xc0,
- 0xf0, 0x48, 0xd3, 0x97, 0x52, 0x9e, 0xee, 0x75, 0x84, 0x0b, 0xe3, 0x82, 0xd8, 0x40, 0x85, 0xa2,
- 0xc5, 0x1c, 0xbb, 0xfa, 0x1d, 0x30, 0x2d, 0xd7, 0xf2, 0xf7, 0x35, 0x65, 0x19, 0xde, 0x6e, 0x2b,
- 0xc1, 0x32, 0xe8, 0x27, 0x88, 0x19, 0x04, 0xbd, 0x35, 0xd8, 0xe3, 0x9c, 0x33, 0x05, 0x73, 0x17,
- 0xdd, 0xe7, 0xea, 0x87, 0xfb, 0xa2, 0x73, 0x47, 0x97, 0x11, 0x6d, 0xc7, 0xbe, 0xdc, 0xd1, 0x87,
- 0x6f, 0xf4, 0x3a, 0x40, 0xbf, 0xeb, 0xaf, 0x17, 0x1e, 0x70, 0x15, 0x86, 0x5d, 0x42, 0xea, 0xd2,
- 0xb9, 0xcc, 0x4e, 0xf3, 0x9a, 0x28, 0xc3, 0x01, 0xf4, 0xf8, 0x39, 0xc1, 0x6b, 0xfd, 0x80, 0x92,
- 0xbb, 0x5d, 0x9e, 0x0c, 0x5e, 0x22, 0x96, 0xa2, 0x97, 0xc9, 0x10, 0x1f, 0x4e, 0x0c, 0x31, 0xba,
- 0x0b, 0xe3, 0xa6, 0xe6, 0x7a, 0xb7, 0x5a, 0x54, 0x6f, 0xf3, 0xf7, 0xcc, 0xe8, 0xc3, 0xf3, 0x79,
+ 0xfe, 0x6c, 0xf3, 0x05, 0x83, 0x09, 0xcc, 0xb7, 0xcb, 0xae, 0xd9, 0x80, 0x60, 0x23, 0x80, 0x80,
+ 0x5d, 0x88, 0x60, 0x31, 0x04, 0x26, 0x08, 0x0c, 0xbb, 0x66, 0x01, 0x81, 0xb5, 0x5e, 0xd8, 0x88,
+ 0x7d, 0xc6, 0x12, 0xb1, 0x44, 0xf4, 0x12, 0xec, 0xc6, 0x7d, 0x64, 0xe6, 0xcd, 0x57, 0xa9, 0x94,
+ 0x25, 0xc9, 0x33, 0x8b, 0x7f, 0x49, 0x75, 0xcf, 0xbd, 0xe7, 0xdc, 0x57, 0x9e, 0x7b, 0xee, 0xb9,
+ 0xe7, 0x01, 0x0b, 0x0d, 0xc3, 0xdb, 0x6a, 0x6f, 0xcc, 0xe9, 0x76, 0xf3, 0x5a, 0x43, 0x73, 0xea,
+ 0xc4, 0x22, 0x4e, 0xf8, 0x4f, 0xeb, 0x76, 0xe3, 0x9a, 0xd6, 0x32, 0xdc, 0x6b, 0xba, 0xed, 0x90,
+ 0x6b, 0xdb, 0x0f, 0x6d, 0x10, 0x4f, 0x7b, 0xe8, 0x5a, 0x83, 0xc2, 0x34, 0x8f, 0xd4, 0xe7, 0x5a,
+ 0x8e, 0xed, 0xd9, 0xe8, 0xe1, 0x10, 0xc7, 0x9c, 0xdf, 0x34, 0xfc, 0xa7, 0x75, 0xbb, 0x31, 0x47,
+ 0x71, 0xcc, 0x51, 0x1c, 0x73, 0x02, 0xc7, 0xec, 0xdb, 0x65, 0xba, 0x76, 0xc3, 0xbe, 0xc6, 0x50,
+ 0x6d, 0xb4, 0x37, 0xd9, 0x2f, 0xf6, 0x83, 0xfd, 0xc7, 0x49, 0xcc, 0x3e, 0x70, 0xfb, 0xdd, 0xee,
+ 0x9c, 0x61, 0xd3, 0xce, 0x5c, 0xd3, 0xda, 0x9e, 0xed, 0xea, 0x9a, 0x69, 0x58, 0x8d, 0x6b, 0xdb,
+ 0x89, 0xde, 0xcc, 0xaa, 0x52, 0x55, 0xd1, 0xed, 0x8e, 0x75, 0x9c, 0x0d, 0x4d, 0x4f, 0xab, 0x73,
+ 0x23, 0xac, 0x43, 0x76, 0x3c, 0x62, 0xb9, 0x86, 0x6d, 0xb9, 0x6f, 0xa7, 0x23, 0x21, 0xce, 0xb6,
+ 0x3c, 0x37, 0x91, 0x0a, 0x69, 0x98, 0x1e, 0x09, 0x31, 0x35, 0x35, 0x7d, 0xcb, 0xb0, 0x88, 0xb3,
+ 0xeb, 0x37, 0xbf, 0xe6, 0x10, 0xd7, 0x6e, 0x3b, 0x3a, 0x39, 0x54, 0x2b, 0xf7, 0x5a, 0x93, 0x78,
+ 0x5a, 0x1a, 0xad, 0x6b, 0x59, 0xad, 0x9c, 0xb6, 0xe5, 0x19, 0xcd, 0x24, 0x99, 0x77, 0x1d, 0xd4,
+ 0xc0, 0xd5, 0xb7, 0x48, 0x53, 0x4b, 0xb4, 0x7b, 0x47, 0x56, 0xbb, 0xb6, 0x67, 0x98, 0xd7, 0x0c,
+ 0xcb, 0x73, 0x3d, 0x27, 0xde, 0x48, 0xfd, 0xa4, 0x02, 0x93, 0xf3, 0xd5, 0x4a, 0x8d, 0xcd, 0xe0,
+ 0xb2, 0xdd, 0x68, 0x18, 0x56, 0x03, 0x3d, 0x08, 0x23, 0xdb, 0xc4, 0xd9, 0xb0, 0x5d, 0xc3, 0xdb,
+ 0x9d, 0x51, 0xae, 0x28, 0x57, 0x07, 0x16, 0xc6, 0xf7, 0xf7, 0x8a, 0x23, 0xcf, 0xfa, 0x85, 0x38,
+ 0x84, 0xa3, 0x0a, 0x9c, 0xde, 0xf2, 0xbc, 0xd6, 0xbc, 0xae, 0x13, 0xd7, 0x0d, 0x6a, 0xcc, 0x14,
+ 0x58, 0xb3, 0x73, 0xfb, 0x7b, 0xc5, 0xd3, 0x37, 0xd6, 0xd6, 0xaa, 0x31, 0x30, 0x4e, 0x6b, 0xa3,
+ 0xfe, 0x82, 0x02, 0x53, 0x41, 0x67, 0x30, 0x79, 0xa5, 0x4d, 0x5c, 0xcf, 0x45, 0x18, 0xce, 0x36,
+ 0xb5, 0x9d, 0x55, 0xdb, 0x5a, 0x69, 0x7b, 0x9a, 0x67, 0x58, 0x8d, 0x8a, 0xb5, 0x69, 0x1a, 0x8d,
+ 0x2d, 0x4f, 0x74, 0x6d, 0x76, 0x7f, 0xaf, 0x78, 0x76, 0x25, 0xb5, 0x06, 0xce, 0x68, 0x49, 0x3b,
+ 0xdd, 0xd4, 0x76, 0x12, 0x08, 0xa5, 0x4e, 0xaf, 0x24, 0xc1, 0x38, 0xad, 0x8d, 0xfa, 0x4e, 0x98,
+ 0xe2, 0xe3, 0xc0, 0xc4, 0xf5, 0x1c, 0x43, 0xf7, 0x0c, 0xdb, 0x42, 0x57, 0xa0, 0xdf, 0xd2, 0x9a,
+ 0x84, 0xf5, 0x70, 0x64, 0x61, 0xec, 0x4b, 0x7b, 0xc5, 0x37, 0xed, 0xef, 0x15, 0xfb, 0x57, 0xb5,
+ 0x26, 0xc1, 0x0c, 0xa2, 0xfe, 0x8f, 0x02, 0x5c, 0x4c, 0xb4, 0x7b, 0xce, 0xf0, 0xb6, 0x6e, 0xb5,
+ 0xe8, 0x7f, 0x2e, 0xfa, 0x41, 0x05, 0xa6, 0xb4, 0x78, 0x05, 0x86, 0x70, 0xf4, 0xe1, 0xc5, 0xb9,
+ 0xc3, 0x7f, 0xe0, 0x73, 0x09, 0x6a, 0x0b, 0xe7, 0x45, 0xbf, 0x92, 0x03, 0xc0, 0x49, 0xd2, 0xe8,
+ 0xe3, 0x0a, 0x0c, 0xd9, 0xbc, 0x73, 0x33, 0x85, 0x2b, 0x7d, 0x57, 0x47, 0x1f, 0xfe, 0xce, 0x23,
+ 0xe9, 0x86, 0x34, 0xe8, 0x39, 0xf1, 0x77, 0xd1, 0xf2, 0x9c, 0xdd, 0x85, 0x53, 0xa2, 0x7b, 0x43,
+ 0xa2, 0x14, 0xfb, 0xe4, 0x67, 0x1f, 0x87, 0x31, 0xb9, 0x26, 0x9a, 0x84, 0xbe, 0xdb, 0x84, 0x6f,
+ 0xd5, 0x11, 0x4c, 0xff, 0x45, 0xd3, 0x30, 0xb0, 0xad, 0x99, 0x6d, 0xc2, 0x96, 0x74, 0x04, 0xf3,
+ 0x1f, 0x8f, 0x17, 0xde, 0xad, 0xa8, 0x0f, 0xc3, 0xc0, 0x7c, 0xbd, 0x6e, 0x5b, 0xe8, 0x01, 0x18,
+ 0x22, 0x96, 0xb6, 0x61, 0x92, 0x3a, 0x6b, 0x38, 0x1c, 0xd2, 0x5b, 0xe4, 0xc5, 0xd8, 0x87, 0xab,
+ 0x3f, 0x56, 0x80, 0x41, 0xd6, 0xc8, 0x45, 0x3f, 0xa2, 0xc0, 0xe9, 0xdb, 0xed, 0x0d, 0xe2, 0x58,
+ 0xc4, 0x23, 0x6e, 0x59, 0x73, 0xb7, 0x36, 0x6c, 0xcd, 0xa9, 0x8b, 0x85, 0xb9, 0x9e, 0x67, 0x46,
+ 0x6e, 0x26, 0xd1, 0xf1, 0x3d, 0x98, 0x02, 0xc0, 0x69, 0xc4, 0xd1, 0x36, 0x8c, 0x59, 0x0d, 0xc3,
+ 0xda, 0xa9, 0x58, 0x0d, 0x87, 0xb8, 0x2e, 0x1b, 0xf4, 0xe8, 0xc3, 0x4f, 0xe7, 0xe9, 0xcc, 0xaa,
+ 0x84, 0x67, 0x61, 0x72, 0x7f, 0xaf, 0x38, 0x26, 0x97, 0xe0, 0x08, 0x1d, 0xf5, 0xef, 0x15, 0x38,
+ 0x35, 0x5f, 0x6f, 0x1a, 0x2e, 0xe5, 0xb4, 0x55, 0xb3, 0xdd, 0x30, 0xba, 0xd8, 0xfa, 0xe8, 0x19,
+ 0x18, 0xd4, 0x6d, 0x6b, 0xd3, 0x68, 0x88, 0x7e, 0xbe, 0x7d, 0x8e, 0x73, 0xae, 0x39, 0x99, 0x73,
+ 0xb1, 0xee, 0x09, 0x8e, 0x37, 0x87, 0xb5, 0x3b, 0x8b, 0x3e, 0x43, 0x5f, 0x80, 0xfd, 0xbd, 0xe2,
+ 0x60, 0x89, 0x21, 0xc0, 0x02, 0x11, 0xba, 0x0a, 0xc3, 0x75, 0xc3, 0xe5, 0x8b, 0xd9, 0xc7, 0x16,
+ 0x73, 0x6c, 0x7f, 0xaf, 0x38, 0x5c, 0x16, 0x65, 0x38, 0x80, 0xa2, 0x65, 0x98, 0xa6, 0x33, 0xc8,
+ 0xdb, 0xd5, 0x88, 0xee, 0x10, 0x8f, 0x76, 0x6d, 0xa6, 0x9f, 0x75, 0x77, 0x66, 0x7f, 0xaf, 0x38,
+ 0x7d, 0x33, 0x05, 0x8e, 0x53, 0x5b, 0xa9, 0x4b, 0x30, 0x3c, 0x6f, 0x12, 0x87, 0x32, 0x04, 0xf4,
+ 0x38, 0x4c, 0x90, 0xa6, 0x66, 0x98, 0x98, 0xe8, 0xc4, 0xd8, 0x26, 0x8e, 0x3b, 0xa3, 0x5c, 0xe9,
+ 0xbb, 0x3a, 0xb2, 0x80, 0xf6, 0xf7, 0x8a, 0x13, 0x8b, 0x11, 0x08, 0x8e, 0xd5, 0x54, 0x3f, 0xa2,
+ 0xc0, 0xe8, 0x7c, 0xbb, 0x6e, 0x78, 0x7c, 0x5c, 0xc8, 0x81, 0x51, 0x8d, 0xfe, 0xac, 0xda, 0xa6,
+ 0xa1, 0xef, 0x8a, 0xcd, 0xf5, 0x54, 0xae, 0xcf, 0x2d, 0x44, 0xb3, 0x70, 0x6a, 0x7f, 0xaf, 0x38,
+ 0x2a, 0x15, 0x60, 0x99, 0x88, 0xba, 0x05, 0x32, 0x0c, 0xbd, 0x0f, 0xc6, 0xf8, 0x70, 0x57, 0xb4,
+ 0x16, 0x26, 0x9b, 0xa2, 0x0f, 0xf7, 0x49, 0x6b, 0xe5, 0x13, 0x9a, 0xbb, 0xb5, 0xf1, 0x32, 0xd1,
+ 0x3d, 0x4c, 0x36, 0x89, 0x43, 0x2c, 0x9d, 0xf0, 0x6d, 0x53, 0x92, 0x1a, 0xe3, 0x08, 0x2a, 0xf5,
+ 0xff, 0x51, 0xe0, 0xd2, 0x7c, 0xdb, 0xdb, 0xb2, 0x1d, 0xe3, 0x2e, 0x71, 0xc2, 0xe9, 0x0e, 0x30,
+ 0xa0, 0x27, 0x61, 0x42, 0x0b, 0x2a, 0xac, 0x86, 0xdb, 0xe9, 0xac, 0xd8, 0x4e, 0x13, 0xf3, 0x11,
+ 0x28, 0x8e, 0xd5, 0x46, 0x0f, 0x03, 0xb8, 0xe1, 0xda, 0x32, 0x1e, 0xb0, 0x80, 0x44, 0x5b, 0x90,
+ 0x56, 0x55, 0xaa, 0xa5, 0xfe, 0x05, 0x3d, 0x0a, 0xb7, 0x35, 0xc3, 0xd4, 0x36, 0x0c, 0xd3, 0xf0,
+ 0x76, 0x5f, 0xb0, 0x2d, 0xd2, 0xc5, 0x6e, 0x5e, 0x87, 0x73, 0x6d, 0x4b, 0xe3, 0xed, 0x4c, 0xb2,
+ 0xc2, 0xf7, 0xef, 0xda, 0x6e, 0x8b, 0x70, 0x2e, 0x39, 0xb2, 0x70, 0x61, 0x7f, 0xaf, 0x78, 0x6e,
+ 0x3d, 0xbd, 0x0a, 0xce, 0x6a, 0x4b, 0x4f, 0x3d, 0x09, 0xf4, 0xac, 0x6d, 0xb6, 0x9b, 0x02, 0x6b,
+ 0x1f, 0xc3, 0xca, 0x4e, 0xbd, 0xf5, 0xd4, 0x1a, 0x38, 0xa3, 0xa5, 0xfa, 0x85, 0x02, 0x0c, 0x2e,
+ 0x68, 0xfa, 0xed, 0x76, 0x0b, 0xbd, 0x0d, 0x86, 0x5b, 0x8e, 0xbd, 0x6d, 0xd4, 0x89, 0x23, 0xc6,
+ 0x36, 0x29, 0xc6, 0x36, 0x5c, 0x15, 0xe5, 0x38, 0xa8, 0x81, 0x0c, 0x98, 0xf0, 0xff, 0x2f, 0xf5,
+ 0xf0, 0xe5, 0xb2, 0x2f, 0xa1, 0x1a, 0x41, 0x84, 0x63, 0x88, 0x91, 0x0a, 0x83, 0x0e, 0x69, 0xd0,
+ 0xa3, 0xae, 0x8f, 0x75, 0x8b, 0x7d, 0xed, 0x98, 0x95, 0x60, 0x01, 0x41, 0xef, 0x87, 0x09, 0xdd,
+ 0x21, 0x75, 0x62, 0x79, 0x86, 0x66, 0xba, 0x74, 0x73, 0x0e, 0x74, 0xbf, 0x39, 0x59, 0x27, 0x4a,
+ 0x91, 0xe6, 0x38, 0x86, 0x4e, 0xfd, 0x52, 0x01, 0xc6, 0xf8, 0x44, 0x2d, 0xb4, 0xf5, 0xdb, 0xc4,
+ 0x43, 0xdf, 0x05, 0xc3, 0x54, 0xbe, 0xab, 0x6b, 0x9e, 0x26, 0x3e, 0x84, 0x6f, 0xcb, 0x1c, 0x3a,
+ 0xfb, 0x06, 0x69, 0xed, 0x90, 0xfa, 0x0a, 0xf1, 0xb4, 0x70, 0xff, 0x85, 0x65, 0x38, 0xc0, 0x8a,
+ 0x36, 0xa1, 0xdf, 0x6d, 0x11, 0x5d, 0x4c, 0x6c, 0x39, 0xcf, 0xa7, 0x2e, 0xf7, 0xb8, 0xd6, 0x22,
+ 0x7a, 0xb8, 0x5d, 0xe9, 0x2f, 0xcc, 0xf0, 0x23, 0x0b, 0x06, 0x5d, 0x4f, 0xf3, 0xda, 0x2e, 0x9b,
+ 0xdf, 0xd1, 0x87, 0x97, 0x7a, 0xa6, 0xc4, 0xb0, 0x2d, 0x4c, 0x08, 0x5a, 0x83, 0xfc, 0x37, 0x16,
+ 0x54, 0xd4, 0x7f, 0xa3, 0xc0, 0xa4, 0x5c, 0x7d, 0xd9, 0x70, 0x3d, 0xf4, 0x1d, 0x89, 0xe9, 0x9c,
+ 0xeb, 0x6e, 0x3a, 0x69, 0x6b, 0x36, 0x99, 0xc1, 0x6e, 0xf5, 0x4b, 0xa4, 0xa9, 0x24, 0x30, 0x60,
+ 0x78, 0xa4, 0xe9, 0x4b, 0x29, 0x4f, 0xf7, 0x3a, 0xc2, 0x85, 0x71, 0x41, 0x6c, 0xa0, 0x42, 0xd1,
+ 0x62, 0x8e, 0x5d, 0xfd, 0x2e, 0x98, 0x96, 0x6b, 0xf9, 0xfb, 0x9a, 0xb2, 0x0c, 0x6f, 0xb7, 0x95,
+ 0x60, 0x19, 0xf4, 0x13, 0xc4, 0x0c, 0x82, 0xde, 0x1a, 0xec, 0x71, 0xce, 0x99, 0x82, 0xb9, 0x8b,
+ 0xee, 0x73, 0xf5, 0xc3, 0x7d, 0xd1, 0xb9, 0xa3, 0xcb, 0x88, 0xb6, 0x63, 0x5f, 0xee, 0xe8, 0xc3,
+ 0x37, 0x7a, 0x1d, 0xa0, 0xdf, 0xf5, 0xd7, 0x0b, 0x0f, 0xb8, 0x0a, 0xc3, 0x2e, 0x21, 0x75, 0xe9,
+ 0x5c, 0x66, 0xa7, 0x79, 0x4d, 0x94, 0xe1, 0x00, 0x7a, 0xfc, 0x9c, 0xe0, 0xb5, 0x7e, 0x40, 0xc9,
+ 0xdd, 0x2e, 0x4f, 0x06, 0x2f, 0x11, 0x4b, 0xd1, 0xcb, 0x64, 0x88, 0x0f, 0x27, 0x86, 0x18, 0xdd,
+ 0x85, 0x71, 0x53, 0x73, 0xbd, 0x5b, 0x2d, 0x7a, 0x6f, 0xf3, 0xf7, 0xcc, 0xe8, 0xc3, 0xf3, 0x79,
0x16, 0x7d, 0x59, 0x46, 0xb4, 0x30, 0xb5, 0xbf, 0x57, 0x1c, 0x8f, 0x14, 0xe1, 0x28, 0x29, 0xf4,
0x32, 0x8c, 0xd0, 0x82, 0x45, 0xc7, 0xb1, 0x1d, 0xc1, 0x2f, 0x9e, 0xc8, 0x4b, 0x97, 0x21, 0xe1,
- 0x7a, 0x64, 0xf0, 0x13, 0x87, 0xe8, 0xd1, 0x7b, 0x01, 0xd9, 0x1b, 0x4c, 0x93, 0xaf, 0x5f, 0xe7,
- 0x4a, 0x2a, 0x1d, 0x2c, 0x5d, 0xfe, 0xbe, 0x85, 0x59, 0xb1, 0x2f, 0xd1, 0xad, 0x44, 0x0d, 0x9c,
- 0xd2, 0x0a, 0xdd, 0x06, 0x14, 0x28, 0xba, 0xfc, 0xb4, 0x3f, 0x60, 0x6b, 0x04, 0x95, 0xc4, 0xd6,
- 0x38, 0x4b, 0x89, 0x5d, 0x4f, 0xa0, 0xc0, 0x29, 0x68, 0xd5, 0xdf, 0x2c, 0xc0, 0x28, 0xdf, 0x22,
- 0x5c, 0x19, 0x39, 0xfe, 0xb3, 0x82, 0x44, 0xce, 0x8a, 0x52, 0xfe, 0xcf, 0x9f, 0x75, 0x38, 0xf3,
- 0xa8, 0x68, 0xc6, 0x8e, 0x8a, 0xc5, 0x5e, 0x09, 0x75, 0x3e, 0x29, 0xfe, 0x58, 0x81, 0x53, 0x52,
- 0xed, 0x13, 0x38, 0x28, 0xea, 0xd1, 0x83, 0xe2, 0xa9, 0x1e, 0xc7, 0x97, 0x71, 0x4e, 0xd8, 0x91,
- 0x61, 0x31, 0x1e, 0xfe, 0x30, 0xc0, 0x06, 0x63, 0x27, 0x92, 0x68, 0x1b, 0x2c, 0xf9, 0x42, 0x00,
- 0xc1, 0x52, 0xad, 0x08, 0x53, 0x2c, 0x74, 0x62, 0x8a, 0xea, 0x7f, 0xe8, 0x83, 0xa9, 0xc4, 0xb4,
- 0x27, 0xf9, 0x88, 0xf2, 0x75, 0xe2, 0x23, 0x85, 0xaf, 0x07, 0x1f, 0xe9, 0xcb, 0xc5, 0x47, 0xba,
- 0x3f, 0x88, 0x1c, 0x40, 0x4d, 0xa3, 0xc1, 0x9b, 0xd5, 0x3c, 0xcd, 0xf1, 0xd6, 0x8c, 0x26, 0x11,
- 0x1c, 0xe7, 0x9b, 0xbb, 0xdb, 0xb2, 0xb4, 0x05, 0x67, 0x3c, 0x2b, 0x09, 0x4c, 0x38, 0x05, 0xbb,
- 0xfa, 0x5d, 0x05, 0x18, 0x5a, 0xd0, 0x5c, 0xd6, 0xd3, 0x0f, 0xc2, 0x98, 0x40, 0x5d, 0x69, 0x6a,
- 0x0d, 0xd2, 0x8b, 0x39, 0x42, 0xa0, 0x5c, 0x91, 0xd0, 0x71, 0x8d, 0x4e, 0x2e, 0xc1, 0x11, 0x72,
- 0x68, 0x17, 0x46, 0x9b, 0xa1, 0xf6, 0x22, 0x96, 0x78, 0xa9, 0x77, 0xea, 0x14, 0x1b, 0x57, 0x5b,
- 0xa5, 0x02, 0x2c, 0xd3, 0x52, 0x5f, 0x82, 0xd3, 0x29, 0x3d, 0xee, 0x42, 0x71, 0x7b, 0x0b, 0x0c,
- 0x51, 0xdd, 0x3b, 0x14, 0xc3, 0x46, 0xf7, 0xf7, 0x8a, 0x43, 0xcf, 0xf2, 0x22, 0xec, 0xc3, 0xd4,
- 0x77, 0x51, 0x01, 0x20, 0xde, 0xa7, 0x6e, 0x0c, 0x7c, 0x03, 0x00, 0xa5, 0x79, 0x6c, 0x7b, 0x7c,
- 0x2b, 0x3d, 0x05, 0x03, 0xad, 0x2d, 0xcd, 0xf5, 0x5b, 0x3c, 0xe0, 0xb3, 0x8a, 0x2a, 0x2d, 0xbc,
- 0xb7, 0x57, 0x9c, 0x91, 0x05, 0x11, 0xd1, 0x88, 0xc1, 0x30, 0x6f, 0x47, 0x77, 0x18, 0xdd, 0xe4,
- 0x25, 0xbb, 0xd9, 0x32, 0x09, 0x85, 0xb2, 0x1d, 0x56, 0xc8, 0xb7, 0xc3, 0x96, 0x13, 0x98, 0x70,
- 0x0a, 0x76, 0x9f, 0x66, 0xc5, 0x32, 0x3c, 0x43, 0x0b, 0x68, 0xf6, 0xe5, 0xa7, 0x19, 0xc5, 0x84,
- 0x53, 0xb0, 0xa3, 0x4f, 0x2a, 0x30, 0x1b, 0x2d, 0x5e, 0x32, 0x2c, 0xc3, 0xdd, 0x22, 0x75, 0x46,
- 0xbc, 0xff, 0xd0, 0xc4, 0x2f, 0xef, 0xef, 0x15, 0x67, 0x97, 0x33, 0x31, 0xe2, 0x0e, 0xd4, 0xd0,
- 0xf7, 0x29, 0x70, 0x21, 0x36, 0x2f, 0x8e, 0xd1, 0x68, 0x10, 0x47, 0xf4, 0xe6, 0xf0, 0x1f, 0x78,
- 0x71, 0x7f, 0xaf, 0x78, 0x61, 0x39, 0x1b, 0x25, 0xee, 0x44, 0x0f, 0xfd, 0x84, 0x02, 0x67, 0x5b,
- 0xc4, 0xaa, 0x1b, 0x56, 0xe3, 0x39, 0xdb, 0xb9, 0x4d, 0x1c, 0x17, 0xdb, 0xa6, 0x69, 0xb7, 0x3d,
- 0x77, 0x66, 0x90, 0x9d, 0x61, 0x95, 0x3c, 0xdf, 0x5c, 0x35, 0x0d, 0xe3, 0xc2, 0x65, 0xb1, 0x45,
- 0xcf, 0xa6, 0x82, 0x5d, 0x9c, 0xd1, 0x11, 0xf5, 0x37, 0x14, 0xe8, 0x2b, 0xe1, 0x0a, 0x7a, 0x30,
- 0xf2, 0x89, 0x9c, 0x93, 0x3f, 0x91, 0x7b, 0x7b, 0xc5, 0xa1, 0x12, 0xae, 0x48, 0x1f, 0xe3, 0xf7,
- 0x29, 0x30, 0xa5, 0xdb, 0x96, 0xa7, 0xd1, 0xb9, 0xc3, 0x5c, 0x56, 0xf6, 0xcf, 0xe5, 0x5c, 0xca,
- 0x70, 0x29, 0x86, 0x2c, 0x34, 0x76, 0xc7, 0x21, 0x2e, 0x4e, 0x52, 0x56, 0x3f, 0xaf, 0xc0, 0x74,
- 0x49, 0x6b, 0x09, 0x53, 0x50, 0x99, 0x6c, 0x1a, 0x74, 0x83, 0x74, 0x63, 0xd9, 0x47, 0x5b, 0x30,
- 0xc8, 0xac, 0xcd, 0x6e, 0x2f, 0xba, 0x7c, 0x48, 0xfb, 0x59, 0x86, 0x8b, 0xdb, 0x41, 0xf8, 0xff,
- 0x58, 0xe0, 0x57, 0x9f, 0x80, 0xc9, 0x78, 0x3d, 0x54, 0xf4, 0x65, 0x1a, 0x6e, 0x7c, 0x1c, 0x89,
- 0x8b, 0x23, 0x8f, 0x0f, 0xff, 0xff, 0xaf, 0x15, 0xdf, 0xf4, 0xe1, 0x3f, 0xbb, 0xf2, 0x26, 0xf5,
- 0x2b, 0x0a, 0x8c, 0x95, 0x4c, 0xbb, 0x5d, 0xaf, 0x3a, 0xf6, 0xa6, 0x61, 0x92, 0x37, 0x86, 0x95,
- 0x43, 0xee, 0x71, 0x96, 0xe8, 0xca, 0xac, 0x0e, 0x72, 0xc5, 0x37, 0x88, 0xd5, 0x41, 0xee, 0x72,
- 0x86, 0x34, 0xf9, 0x22, 0x9c, 0x91, 0x6b, 0x85, 0x26, 0xd3, 0x2b, 0xd0, 0x7f, 0xdb, 0xb0, 0xea,
- 0xf1, 0x8d, 0x79, 0xd3, 0xb0, 0xea, 0x98, 0x41, 0x82, 0xad, 0x5b, 0xc8, 0x3c, 0xb3, 0xfe, 0x66,
- 0x24, 0x3a, 0x6d, 0x4c, 0x58, 0xbd, 0x0a, 0xc3, 0xba, 0xb6, 0xd0, 0xb6, 0xea, 0x66, 0xb0, 0xeb,
- 0xe9, 0x14, 0x94, 0xe6, 0x79, 0x19, 0x0e, 0xa0, 0xe8, 0x2e, 0x40, 0x78, 0x3b, 0xd1, 0x8b, 0x10,
- 0x10, 0x5e, 0x7c, 0xd4, 0x88, 0xe7, 0x19, 0x56, 0xc3, 0x0d, 0xf7, 0x55, 0x08, 0xc3, 0x12, 0x35,
- 0xf4, 0x41, 0x18, 0x97, 0x25, 0x12, 0x6e, 0x26, 0xcd, 0xb9, 0x0c, 0x11, 0xd1, 0xe7, 0x8c, 0x20,
- 0x3c, 0x2e, 0x97, 0xba, 0x38, 0x4a, 0x0d, 0xed, 0x06, 0xf2, 0x17, 0x37, 0xd2, 0xf6, 0xe7, 0xd7,
- 0x28, 0x64, 0xd1, 0x67, 0x5a, 0x10, 0x1f, 0x8b, 0x18, 0x8d, 0x23, 0xa4, 0x52, 0x0c, 0x33, 0x03,
- 0xc7, 0x65, 0x98, 0x21, 0x30, 0xc4, 0x4d, 0x53, 0xfe, 0x71, 0xf3, 0x78, 0x9e, 0x01, 0x72, 0x2b,
- 0x57, 0x78, 0xdd, 0xc6, 0x7f, 0xbb, 0xd8, 0xc7, 0x8d, 0xb6, 0x61, 0x8c, 0x0a, 0xd6, 0x35, 0x62,
- 0x12, 0xdd, 0xb3, 0x9d, 0x99, 0xa1, 0xfc, 0xd7, 0x59, 0x35, 0x09, 0x0f, 0x97, 0x62, 0xe5, 0x12,
- 0x1c, 0xa1, 0x13, 0x58, 0xee, 0x86, 0x33, 0x2d, 0x77, 0x6d, 0x18, 0xdd, 0x96, 0x4c, 0xf1, 0x23,
- 0x6c, 0x12, 0x9e, 0xcc, 0xd3, 0xb1, 0xd0, 0x2e, 0xbf, 0x70, 0x5a, 0x10, 0x1a, 0x95, 0x6d, 0xf8,
- 0x32, 0x1d, 0xb4, 0x01, 0x43, 0x1b, 0x5c, 0x06, 0x9d, 0x01, 0x36, 0x17, 0xef, 0xe9, 0x41, 0xb4,
- 0xe6, 0x72, 0xae, 0xf8, 0x81, 0x7d, 0xc4, 0xe8, 0x25, 0x18, 0x34, 0x8d, 0xa6, 0xe1, 0xb9, 0x33,
- 0xa3, 0x8c, 0x44, 0xae, 0xa5, 0x5d, 0x66, 0x18, 0xf8, 0x61, 0xc5, 0xff, 0xc7, 0x02, 0x2b, 0xfa,
- 0xb4, 0x02, 0xa7, 0xc5, 0x36, 0x0c, 0x0e, 0x2d, 0x83, 0xb8, 0x33, 0x63, 0x6c, 0x0e, 0x6f, 0xf4,
- 0x76, 0x48, 0x86, 0x07, 0xf4, 0xc2, 0x05, 0x31, 0x9b, 0xa7, 0x57, 0x92, 0xc4, 0x70, 0x5a, 0x0f,
- 0xd4, 0x7f, 0x39, 0x0e, 0x53, 0x25, 0xb3, 0xed, 0x7a, 0xc4, 0x99, 0x17, 0x9e, 0x2c, 0xc4, 0x41,
- 0x1f, 0x55, 0xe0, 0x2c, 0xfb, 0xb7, 0x6c, 0xdf, 0xb1, 0xca, 0xc4, 0xd4, 0x76, 0xe7, 0x37, 0x69,
- 0x8d, 0x7a, 0xfd, 0x70, 0x87, 0x47, 0xb9, 0x2d, 0xd4, 0x64, 0x76, 0x63, 0x53, 0x4b, 0xc5, 0x88,
- 0x33, 0x28, 0xa1, 0xef, 0x55, 0xe0, 0x7c, 0x0a, 0xa8, 0x4c, 0x4c, 0xe2, 0xf9, 0xc2, 0xff, 0x61,
- 0xfb, 0x71, 0x69, 0x7f, 0xaf, 0x78, 0xbe, 0x96, 0x85, 0x14, 0x67, 0xd3, 0x43, 0xdf, 0xaf, 0xc0,
- 0x6c, 0x0a, 0x74, 0x49, 0x33, 0xcc, 0xb6, 0xe3, 0xeb, 0x05, 0x87, 0xed, 0x0e, 0x13, 0xcf, 0x6b,
- 0x99, 0x58, 0x71, 0x07, 0x8a, 0xe8, 0x43, 0x70, 0x26, 0x80, 0xae, 0x5b, 0x16, 0x21, 0xf5, 0x88,
- 0x96, 0x70, 0xd8, 0xae, 0x9c, 0xdf, 0xdf, 0x2b, 0x9e, 0xa9, 0xa5, 0x21, 0xc4, 0xe9, 0x74, 0x50,
- 0x03, 0x2e, 0x85, 0x00, 0xcf, 0x30, 0x8d, 0xbb, 0x5c, 0x91, 0xd9, 0x72, 0x88, 0xbb, 0x65, 0x9b,
- 0x75, 0xc6, 0x8a, 0x95, 0x85, 0x37, 0xef, 0xef, 0x15, 0x2f, 0xd5, 0x3a, 0x55, 0xc4, 0x9d, 0xf1,
- 0xa0, 0x3a, 0x8c, 0xb9, 0xba, 0x66, 0x55, 0x2c, 0x8f, 0x38, 0xdb, 0x9a, 0x39, 0x33, 0x98, 0x6b,
- 0x80, 0x9c, 0x01, 0x4a, 0x78, 0x70, 0x04, 0x2b, 0x7a, 0x37, 0x0c, 0x93, 0x9d, 0x96, 0x66, 0xd5,
- 0x09, 0x67, 0xba, 0x23, 0x0b, 0x17, 0xe9, 0x51, 0xbf, 0x28, 0xca, 0xee, 0xed, 0x15, 0xc7, 0xfc,
- 0xff, 0x57, 0xec, 0x3a, 0xc1, 0x41, 0x6d, 0xf4, 0x01, 0x98, 0x66, 0xae, 0x36, 0x75, 0xc2, 0x8e,
- 0x10, 0xd7, 0xd7, 0x15, 0x87, 0x73, 0xf5, 0x93, 0x5d, 0xc3, 0xaf, 0xa4, 0xe0, 0xc3, 0xa9, 0x54,
- 0xe8, 0x32, 0x34, 0xb5, 0x9d, 0xeb, 0x8e, 0xa6, 0x93, 0xcd, 0xb6, 0xb9, 0x46, 0x9c, 0xa6, 0x61,
- 0x71, 0x63, 0x09, 0xd1, 0x6d, 0xab, 0x4e, 0x19, 0xb5, 0x72, 0x75, 0x80, 0x2f, 0xc3, 0x4a, 0xa7,
- 0x8a, 0xb8, 0x33, 0x1e, 0xf4, 0x08, 0x8c, 0x19, 0x0d, 0xcb, 0x76, 0xc8, 0x9a, 0x66, 0x58, 0x9e,
- 0x3b, 0x03, 0x4c, 0xc8, 0x66, 0xd3, 0x5a, 0x91, 0xca, 0x71, 0xa4, 0x16, 0xda, 0x06, 0x64, 0x91,
- 0x3b, 0x55, 0xbb, 0xce, 0xb6, 0xc0, 0x7a, 0x8b, 0x6d, 0x64, 0xc1, 0x66, 0x0f, 0x3b, 0x35, 0x4c,
- 0x95, 0x5e, 0x4d, 0x60, 0xc3, 0x29, 0x14, 0xd0, 0x12, 0xa0, 0xa6, 0xb6, 0xb3, 0xd8, 0x6c, 0x79,
- 0xbb, 0x0b, 0x6d, 0xf3, 0xb6, 0xe0, 0x1a, 0x63, 0x6c, 0x2e, 0xb8, 0xa1, 0x29, 0x01, 0xc5, 0x29,
- 0x2d, 0x90, 0x06, 0x17, 0xf8, 0x78, 0xca, 0x1a, 0x69, 0xda, 0x96, 0x4b, 0x3c, 0x57, 0xda, 0xa4,
- 0x33, 0xe3, 0xcc, 0xe1, 0x82, 0x29, 0xb6, 0x95, 0xec, 0x6a, 0xb8, 0x13, 0x8e, 0xa8, 0xcb, 0xd9,
- 0xc4, 0x01, 0x2e, 0x67, 0x8f, 0xc2, 0xb8, 0xeb, 0x69, 0x8e, 0xd7, 0x6e, 0x89, 0x65, 0x38, 0xc5,
- 0x96, 0x81, 0xd9, 0x21, 0x6b, 0x32, 0x00, 0x47, 0xeb, 0xd1, 0xe5, 0xe3, 0xc6, 0x66, 0xd1, 0x6e,
- 0x32, 0x5c, 0xbe, 0x9a, 0x54, 0x8e, 0x23, 0xb5, 0xd0, 0x3a, 0x9c, 0x6b, 0x6a, 0x3b, 0xc1, 0xe7,
- 0x5b, 0xd5, 0x1c, 0xcd, 0x34, 0x89, 0x69, 0xb8, 0xcd, 0x99, 0x29, 0xd6, 0x53, 0x76, 0xc3, 0xbf,
- 0x92, 0x5e, 0x05, 0x67, 0xb5, 0x15, 0x3e, 0x68, 0x65, 0x47, 0x33, 0x22, 0x28, 0x51, 0xc4, 0x07,
- 0x2d, 0x0e, 0xc6, 0x69, 0x6d, 0xd4, 0xff, 0xd1, 0x0f, 0x33, 0x89, 0x13, 0xcc, 0x77, 0x24, 0x3b,
- 0x90, 0x47, 0x29, 0x47, 0xc4, 0xa3, 0x5a, 0x70, 0x25, 0xa8, 0x70, 0xbd, 0xd5, 0x4e, 0xa5, 0x55,
- 0x60, 0xb4, 0xee, 0xdf, 0xdf, 0x2b, 0x5e, 0xa9, 0x1d, 0x50, 0x17, 0x1f, 0x88, 0x2d, 0x9b, 0xff,
- 0xf7, 0x9d, 0x10, 0xff, 0xff, 0x00, 0x4c, 0x4b, 0x00, 0x87, 0x68, 0xf5, 0xdd, 0x1e, 0xce, 0x1f,
- 0xc6, 0xf6, 0x6a, 0x29, 0xf8, 0x70, 0x2a, 0x95, 0x4c, 0xa6, 0x3b, 0x70, 0x12, 0x4c, 0x57, 0xdd,
- 0xeb, 0x83, 0x91, 0x92, 0x6d, 0xd5, 0xb9, 0x5d, 0xe4, 0xa1, 0xc8, 0xad, 0xf7, 0x25, 0x59, 0x76,
- 0xbe, 0xb7, 0x57, 0x1c, 0x0f, 0x2a, 0x4a, 0xc2, 0xf4, 0x63, 0xc1, 0xfd, 0x12, 0xd7, 0x48, 0xdf,
- 0x1c, 0xbd, 0x18, 0xba, 0xb7, 0x57, 0x3c, 0x15, 0x34, 0x8b, 0xde, 0x15, 0x51, 0x8e, 0x6a, 0x6a,
- 0xae, 0xb7, 0xe6, 0x68, 0x96, 0x6b, 0xf4, 0x60, 0x98, 0x0c, 0x2e, 0x04, 0x96, 0x13, 0xd8, 0x70,
- 0x0a, 0x05, 0xf4, 0x32, 0x4c, 0xd0, 0xd2, 0xf5, 0x56, 0x5d, 0xf3, 0x48, 0x4e, 0x7b, 0x64, 0xe0,
- 0xc3, 0xb4, 0x1c, 0xc1, 0x84, 0x63, 0x98, 0xb9, 0x97, 0x80, 0xe6, 0xda, 0x16, 0x5b, 0xcf, 0x88,
- 0x97, 0x00, 0x2d, 0xc5, 0x02, 0x8a, 0x1e, 0x80, 0xa1, 0x26, 0x71, 0x5d, 0xad, 0x41, 0x98, 0x54,
- 0x30, 0x12, 0x2a, 0x56, 0x2b, 0xbc, 0x18, 0xfb, 0x70, 0xf4, 0x36, 0x18, 0xd0, 0xed, 0x3a, 0x71,
- 0x67, 0x86, 0x18, 0xe3, 0xa3, 0x67, 0xc0, 0x40, 0x89, 0x16, 0xdc, 0xdb, 0x2b, 0x8e, 0xb0, 0xeb,
- 0x13, 0xfa, 0x0b, 0xf3, 0x4a, 0xea, 0x8f, 0x2b, 0x30, 0x19, 0x37, 0x96, 0x75, 0xe1, 0xdd, 0x70,
- 0x72, 0x8e, 0x02, 0xea, 0xa7, 0x15, 0x18, 0xa3, 0x3d, 0x74, 0x6c, 0xb3, 0x6a, 0x6a, 0x16, 0x41,
- 0xdf, 0xa3, 0xc0, 0xe4, 0x96, 0xd1, 0xd8, 0x92, 0xfd, 0xb8, 0x84, 0xb8, 0x9e, 0xcb, 0xd8, 0x74,
- 0x23, 0x86, 0x6b, 0x61, 0x7a, 0x7f, 0xaf, 0x38, 0x19, 0x2f, 0xc5, 0x09, 0x9a, 0xea, 0x5f, 0x16,
- 0xe0, 0x9c, 0xdc, 0xb3, 0xf9, 0xd0, 0x45, 0x1e, 0xfd, 0xb1, 0x02, 0xd0, 0x34, 0xac, 0x79, 0xd3,
- 0xb4, 0xef, 0x30, 0xe7, 0x53, 0xaa, 0x00, 0xbd, 0x98, 0xd7, 0xc8, 0x99, 0x42, 0x61, 0x6e, 0x25,
- 0xc0, 0xce, 0x2f, 0x26, 0x9f, 0xf7, 0x8d, 0x27, 0x21, 0xe0, 0xde, 0x5e, 0xb1, 0x98, 0xf4, 0xcb,
- 0x9f, 0xc3, 0xc2, 0xf9, 0x7d, 0xd9, 0x70, 0xbd, 0x8f, 0xfe, 0x45, 0xc7, 0x2a, 0xfc, 0x86, 0x32,
- 0x1c, 0xc8, 0x6c, 0x13, 0x4e, 0xc5, 0x08, 0xa7, 0x38, 0xe6, 0x96, 0x65, 0xc7, 0xdc, 0x03, 0x98,
- 0xd4, 0x9c, 0xef, 0x8a, 0x3f, 0xf7, 0x4c, 0x5b, 0xb3, 0x3c, 0x3a, 0xd3, 0x92, 0x23, 0xef, 0x9f,
- 0x17, 0x60, 0x5a, 0x4c, 0x80, 0x49, 0x55, 0x94, 0x96, 0x69, 0xef, 0x36, 0x89, 0x75, 0x12, 0xce,
- 0x5a, 0xfe, 0x47, 0x50, 0xc8, 0xfc, 0x08, 0x9a, 0x89, 0x8f, 0xa0, 0x2f, 0xcf, 0x47, 0x10, 0xf0,
- 0x8a, 0x03, 0x0c, 0x33, 0x18, 0xce, 0x1a, 0x16, 0xed, 0xe8, 0x75, 0xb6, 0x61, 0x42, 0x97, 0x4a,
- 0xc6, 0x9f, 0x86, 0xb9, 0xee, 0x59, 0x49, 0xad, 0x81, 0x33, 0x5a, 0xaa, 0x7f, 0xad, 0xc0, 0x4c,
- 0xda, 0xfc, 0x9e, 0x80, 0x2d, 0xb5, 0x19, 0xb5, 0xa5, 0xde, 0xe8, 0xe1, 0xdb, 0x88, 0x74, 0x3d,
- 0xc3, 0xa6, 0xfa, 0x57, 0x05, 0x38, 0x1b, 0x56, 0xaf, 0x58, 0xae, 0xa7, 0x99, 0x26, 0x97, 0x4b,
- 0x8f, 0x7f, 0x2f, 0xb5, 0x22, 0x26, 0xf1, 0xd5, 0xde, 0x86, 0x2a, 0xf7, 0x3d, 0xd3, 0xaf, 0x63,
- 0x27, 0xe6, 0xd7, 0x51, 0x3d, 0x42, 0x9a, 0x9d, 0x5d, 0x3c, 0xfe, 0x93, 0x02, 0xb3, 0xe9, 0x0d,
- 0x4f, 0x60, 0x53, 0xd9, 0xd1, 0x4d, 0xf5, 0xde, 0xa3, 0x1b, 0x75, 0xc6, 0xb6, 0xfa, 0xf9, 0x42,
- 0xd6, 0x68, 0x99, 0x5d, 0x7d, 0x13, 0x4e, 0x39, 0xa4, 0x61, 0xb8, 0x9e, 0x70, 0x40, 0x38, 0x9c,
- 0x8f, 0xb5, 0x7f, 0x9f, 0x76, 0x0a, 0x47, 0x71, 0xe0, 0x38, 0x52, 0xb4, 0x0a, 0x43, 0x2e, 0x21,
- 0x75, 0x8a, 0xbf, 0xd0, 0x3d, 0xfe, 0x40, 0x88, 0xa8, 0xf1, 0xb6, 0xd8, 0x47, 0x82, 0xbe, 0x0d,
- 0xc6, 0xeb, 0xc1, 0x17, 0x45, 0xb1, 0xf6, 0x75, 0x8f, 0x95, 0xa9, 0x68, 0x65, 0xb9, 0x35, 0x8e,
- 0x22, 0x53, 0xff, 0x4e, 0x81, 0x8b, 0x9d, 0xf6, 0x16, 0x7a, 0x05, 0x40, 0xf7, 0xa5, 0x42, 0x57,
- 0x1c, 0x9e, 0x4f, 0xe4, 0x5c, 0x4b, 0x8e, 0x25, 0xfc, 0x40, 0x83, 0x22, 0x17, 0x4b, 0x44, 0x52,
- 0xbc, 0xfd, 0x0a, 0xc7, 0xe4, 0xed, 0xa7, 0xfe, 0x67, 0x45, 0x66, 0x45, 0xf2, 0xda, 0xbe, 0xd1,
- 0x58, 0x91, 0xdc, 0xf7, 0xcc, 0x7b, 0xba, 0x2f, 0x17, 0xe0, 0x4a, 0x7a, 0x13, 0xe9, 0x3c, 0x7f,
- 0x1a, 0x06, 0x5b, 0xfc, 0x1d, 0x04, 0x77, 0x09, 0xbf, 0x4a, 0x39, 0x0b, 0x7f, 0xa5, 0x70, 0x6f,
- 0xaf, 0x38, 0x9b, 0xc6, 0xe8, 0xc5, 0xfb, 0x06, 0xd1, 0x0e, 0x19, 0xb1, 0x0b, 0x05, 0x2e, 0xb4,
- 0xbf, 0xa3, 0x4b, 0xe6, 0xa2, 0x6d, 0x10, 0xb3, 0xeb, 0x3b, 0x84, 0x8f, 0x28, 0x30, 0x11, 0xd9,
- 0xd1, 0xee, 0xcc, 0x00, 0xdb, 0xa3, 0xb9, 0x1c, 0xad, 0x22, 0x9f, 0x4a, 0x28, 0x0d, 0x44, 0x8a,
- 0x5d, 0x1c, 0x23, 0x18, 0x63, 0xb3, 0xf2, 0xac, 0xbe, 0xe1, 0xd8, 0xac, 0xdc, 0xf9, 0x0c, 0x36,
- 0xfb, 0x63, 0x85, 0xac, 0xd1, 0x32, 0x36, 0x7b, 0x07, 0x46, 0x7c, 0x31, 0xd2, 0x67, 0x17, 0x4b,
- 0xbd, 0xf6, 0x89, 0xa3, 0x5b, 0x98, 0x12, 0xfd, 0x19, 0xf1, 0x4b, 0x5c, 0x1c, 0xd2, 0x42, 0xdf,
- 0xad, 0x00, 0x84, 0x0b, 0x23, 0x3e, 0xaa, 0xb5, 0xa3, 0x9b, 0x0e, 0x49, 0xac, 0x99, 0xa0, 0x9f,
- 0xb4, 0xb4, 0x29, 0x24, 0xba, 0xea, 0xbf, 0xe9, 0x07, 0x94, 0xec, 0x7b, 0x77, 0xd7, 0xc5, 0x07,
- 0x08, 0xb9, 0x2d, 0x98, 0x74, 0xa8, 0xb4, 0xa8, 0x1b, 0x26, 0x53, 0x59, 0xed, 0xb6, 0x97, 0xd3,
- 0xf2, 0xc1, 0xd4, 0x2a, 0x1c, 0xc3, 0x85, 0x13, 0xd8, 0xd1, 0x5b, 0x60, 0xa8, 0xe5, 0x18, 0x4d,
- 0xcd, 0xd9, 0x65, 0x4a, 0xf1, 0x30, 0xbf, 0xcb, 0xaa, 0xf2, 0x22, 0xec, 0xc3, 0xd0, 0x07, 0x60,
- 0xc4, 0x34, 0x36, 0x89, 0xbe, 0xab, 0x9b, 0x44, 0x98, 0xca, 0x6f, 0x1d, 0xcd, 0x9a, 0x2f, 0xfb,
- 0x68, 0x85, 0x07, 0xa2, 0xff, 0x13, 0x87, 0x04, 0x51, 0x05, 0x4e, 0xdf, 0x61, 0x3e, 0x31, 0x26,
- 0x71, 0xdd, 0x5a, 0xbb, 0xd5, 0xb2, 0x1d, 0x8f, 0xd4, 0x99, 0x41, 0x7d, 0x98, 0x1b, 0xf6, 0x9e,
- 0x4b, 0x82, 0x71, 0x5a, 0x1b, 0xf4, 0x04, 0x80, 0xd6, 0xf6, 0x6c, 0xfe, 0x20, 0x71, 0x66, 0x98,
- 0x69, 0xed, 0x97, 0xe8, 0x62, 0xcf, 0x07, 0xa5, 0xf7, 0xf6, 0x8a, 0xa3, 0xc2, 0xf6, 0xc7, 0x96,
- 0x46, 0x6a, 0x80, 0x5e, 0x84, 0x69, 0x9d, 0x83, 0x4a, 0x76, 0xb3, 0xa5, 0x79, 0x86, 0xd0, 0x88,
- 0x47, 0x18, 0xa2, 0x6f, 0xda, 0xdf, 0x2b, 0x4e, 0x97, 0x52, 0xe0, 0x71, 0x94, 0xa9, 0x48, 0xd4,
- 0x4f, 0x16, 0xe0, 0x42, 0x87, 0x09, 0x42, 0x98, 0x7e, 0x78, 0x62, 0xfd, 0xc4, 0x36, 0x7b, 0x84,
- 0x7f, 0x2c, 0xa2, 0xf0, 0xde, 0x5e, 0xf1, 0xbe, 0x0e, 0x08, 0x6a, 0x74, 0x9f, 0x93, 0xc6, 0x2e,
- 0x0e, 0xd1, 0xa0, 0x0a, 0x0c, 0xd6, 0xc3, 0xbb, 0xaf, 0x91, 0x85, 0x87, 0xe8, 0x51, 0xc0, 0xad,
- 0xd4, 0xdd, 0x62, 0x13, 0x08, 0xd0, 0x32, 0x0c, 0x71, 0x9f, 0x4a, 0x22, 0x8e, 0x95, 0x87, 0x99,
- 0xc9, 0x84, 0x17, 0x75, 0x8b, 0xcc, 0x47, 0xa1, 0xfe, 0xad, 0x02, 0x43, 0x25, 0xdb, 0x21, 0xe5,
- 0xd5, 0x1a, 0xda, 0x85, 0x51, 0xe9, 0x45, 0xbc, 0x60, 0xb1, 0x39, 0x79, 0x0e, 0xc3, 0x28, 0xa9,
- 0xf6, 0xfe, 0x1b, 0xbe, 0xa0, 0x00, 0xcb, 0xb4, 0xd0, 0x2b, 0x74, 0xce, 0xef, 0x38, 0x86, 0x47,
- 0x09, 0xf7, 0xe2, 0x64, 0xc3, 0x09, 0x63, 0x1f, 0x17, 0xdf, 0xed, 0xc1, 0x4f, 0x1c, 0x52, 0x51,
- 0xab, 0x94, 0xbd, 0xc4, 0xbb, 0x89, 0x1e, 0x87, 0xfe, 0xa6, 0x5d, 0xf7, 0xd7, 0xfd, 0xad, 0x3e,
- 0xf3, 0x58, 0xb1, 0xeb, 0x74, 0x6e, 0xcf, 0x26, 0x5b, 0xb0, 0xfb, 0x24, 0xd6, 0x46, 0x5d, 0x85,
- 0xc9, 0x38, 0x7d, 0xf4, 0x38, 0x4c, 0xe8, 0x76, 0xb3, 0x69, 0x5b, 0xb5, 0xf6, 0xe6, 0xa6, 0xb1,
- 0x43, 0x22, 0x8f, 0x2b, 0x4b, 0x11, 0x08, 0x8e, 0xd5, 0x54, 0x3f, 0xa7, 0x40, 0x1f, 0x5d, 0x17,
- 0x15, 0x06, 0xeb, 0x76, 0x53, 0x33, 0x2c, 0xd1, 0x2b, 0x76, 0x4b, 0x5d, 0x66, 0x25, 0x58, 0x40,
- 0x50, 0x0b, 0x46, 0x7c, 0x89, 0xac, 0x27, 0xb7, 0xf0, 0xf2, 0x6a, 0x2d, 0x78, 0x55, 0x13, 0x1c,
- 0x13, 0x7e, 0x89, 0x8b, 0x43, 0x22, 0xaa, 0x06, 0x53, 0xe5, 0xd5, 0x5a, 0xc5, 0xd2, 0xcd, 0x76,
- 0x9d, 0x2c, 0xee, 0xb0, 0x3f, 0x94, 0xcf, 0x19, 0xbc, 0x44, 0x8c, 0x93, 0xf1, 0x39, 0x51, 0x09,
- 0xfb, 0x30, 0x5a, 0x8d, 0xf0, 0x16, 0xe2, 0xad, 0x21, 0xab, 0x26, 0x90, 0x60, 0x1f, 0xa6, 0x7e,
- 0xa5, 0x00, 0xa3, 0x52, 0x87, 0x90, 0x09, 0x43, 0x7c, 0xb8, 0x6e, 0x2f, 0xef, 0xc9, 0x13, 0xbd,
- 0xe6, 0xd4, 0xf9, 0x84, 0xba, 0xd8, 0x27, 0x21, 0xf3, 0xec, 0x42, 0x07, 0x9e, 0x3d, 0x17, 0x79,
- 0xb2, 0xc9, 0x3f, 0xc9, 0x89, 0xec, 0xe7, 0x9a, 0xe8, 0xa2, 0x38, 0x9e, 0xb8, 0x5f, 0xf6, 0x70,
- 0xec, 0x68, 0xda, 0x84, 0x81, 0xbb, 0xb6, 0x45, 0x5c, 0x61, 0x0b, 0x3f, 0xa2, 0x01, 0x32, 0x6f,
- 0xba, 0x17, 0x28, 0x5e, 0xcc, 0xd1, 0xab, 0x3f, 0xa1, 0x00, 0x94, 0x35, 0x4f, 0xe3, 0xae, 0x1b,
- 0x5d, 0x78, 0x07, 0x5e, 0x8c, 0x9c, 0xaa, 0xc3, 0x89, 0x97, 0x61, 0xfd, 0xae, 0x71, 0xd7, 0x1f,
- 0x7e, 0x20, 0xad, 0x73, 0xec, 0x35, 0xe3, 0x2e, 0xc1, 0x0c, 0x8e, 0x1e, 0x84, 0x11, 0x62, 0xe9,
- 0xce, 0x6e, 0x8b, 0x1e, 0x2c, 0xdc, 0xc4, 0xc3, 0xbe, 0xd0, 0x45, 0xbf, 0x10, 0x87, 0x70, 0xf5,
- 0x21, 0x88, 0xaa, 0x5c, 0x5d, 0x38, 0x2f, 0xff, 0xbd, 0x02, 0xe7, 0xca, 0x6d, 0xcd, 0x9c, 0x6f,
- 0xd1, 0x8d, 0xaa, 0x99, 0x4b, 0x36, 0xf7, 0x01, 0xa0, 0x7a, 0xc8, 0xdb, 0x60, 0xd8, 0x17, 0x72,
- 0xe2, 0x4f, 0x47, 0x7d, 0x46, 0x89, 0x83, 0x1a, 0x48, 0x83, 0x61, 0xd7, 0x17, 0xbb, 0x0b, 0x3d,
- 0x88, 0xdd, 0x3e, 0x89, 0x40, 0xec, 0x0e, 0xd0, 0x72, 0xe3, 0x17, 0x5b, 0xa0, 0x1a, 0x71, 0xb6,
- 0x0d, 0x9d, 0xcc, 0xeb, 0xba, 0xdd, 0xb6, 0x3c, 0x57, 0x3c, 0x05, 0x17, 0xc6, 0xaf, 0xb4, 0x1a,
- 0x38, 0xa3, 0xa5, 0xfa, 0x25, 0x05, 0xfa, 0x17, 0xd7, 0x4a, 0x65, 0xf4, 0x6d, 0xd0, 0x1f, 0xb0,
- 0x8c, 0x9c, 0xae, 0x3e, 0x14, 0x0f, 0xb7, 0xd3, 0xf1, 0xf5, 0x5e, 0xa1, 0x0c, 0x87, 0x61, 0x45,
- 0x1b, 0x30, 0x48, 0xb6, 0x09, 0xed, 0x6a, 0xe1, 0x48, 0xf0, 0x33, 0x96, 0xb6, 0xc8, 0x30, 0x62,
- 0x81, 0x59, 0xfd, 0x94, 0x02, 0x10, 0x56, 0x41, 0xdf, 0x99, 0x76, 0x3a, 0xdd, 0x3c, 0x42, 0xeb,
- 0x73, 0xe7, 0x23, 0x4a, 0xfd, 0xb5, 0x01, 0x38, 0x4f, 0xbb, 0x23, 0xb6, 0xaa, 0x61, 0x5b, 0x37,
- 0xc9, 0xee, 0x37, 0xdc, 0xe4, 0xbf, 0xe1, 0x26, 0x7f, 0x84, 0x6e, 0xf2, 0x2f, 0xc2, 0x79, 0xba,
- 0xe5, 0x04, 0x98, 0x30, 0x9f, 0xa1, 0xaa, 0x43, 0x5a, 0x9a, 0x43, 0xea, 0x4c, 0x1f, 0x18, 0xe6,
- 0x5e, 0x50, 0xf3, 0x59, 0x95, 0x70, 0x76, 0x7b, 0xf5, 0x29, 0x98, 0x0c, 0xf7, 0xae, 0xf8, 0xa8,
- 0x1e, 0x8c, 0x2b, 0x99, 0x23, 0xbe, 0xc4, 0x94, 0x54, 0x0c, 0xd5, 0x7b, 0x0a, 0x4c, 0x2e, 0xee,
- 0xb4, 0x0c, 0x87, 0xbd, 0xcf, 0xe7, 0xcf, 0x4c, 0xd0, 0x03, 0xe1, 0x6b, 0x14, 0x25, 0x7a, 0x8b,
- 0x17, 0x7f, 0x91, 0x82, 0x36, 0x61, 0x82, 0xb0, 0xe6, 0x4c, 0x0b, 0xd4, 0xbc, 0x3c, 0xdb, 0x9b,
- 0x07, 0xa5, 0x88, 0x60, 0xc1, 0x31, 0xac, 0xa8, 0x06, 0x13, 0xba, 0xa9, 0xb9, 0xae, 0xb1, 0x69,
- 0xe8, 0xe1, 0x2b, 0xaa, 0x91, 0x85, 0x07, 0x99, 0xcc, 0x15, 0x81, 0xdc, 0xdb, 0x2b, 0x9e, 0x11,
- 0xfd, 0x8c, 0x02, 0x70, 0x0c, 0x85, 0xfa, 0x99, 0x02, 0x8c, 0x2f, 0xee, 0xb4, 0x6c, 0xb7, 0xed,
- 0x10, 0x56, 0xf5, 0x04, 0xec, 0x5a, 0x0f, 0xc0, 0xd0, 0x96, 0x66, 0xd5, 0x4d, 0xe2, 0x88, 0x63,
- 0x37, 0x98, 0xdb, 0x1b, 0xbc, 0x18, 0xfb, 0x70, 0xf4, 0x2a, 0x80, 0xab, 0x6f, 0x91, 0x7a, 0x9b,
- 0x31, 0xc7, 0xbe, 0xfc, 0xcc, 0x31, 0x32, 0xc6, 0x5a, 0x80, 0x52, 0x88, 0x34, 0xc1, 0x6f, 0x2c,
- 0x91, 0x53, 0xff, 0x44, 0x81, 0xa9, 0x48, 0xbb, 0x13, 0x30, 0xd7, 0x6c, 0x46, 0xcd, 0x35, 0xf3,
- 0x3d, 0x8f, 0x35, 0xc3, 0x4a, 0xf3, 0xf1, 0x02, 0x9c, 0xcb, 0x98, 0x93, 0x84, 0xbf, 0xaf, 0x72,
- 0x42, 0xfe, 0xbe, 0x6d, 0x18, 0xf5, 0x6c, 0x53, 0x3c, 0xf6, 0xf3, 0x67, 0x20, 0xd7, 0x11, 0xbc,
- 0x16, 0xa0, 0x09, 0xbd, 0x79, 0xc3, 0x32, 0x17, 0xcb, 0x74, 0xd4, 0xdf, 0x50, 0x60, 0x24, 0xb0,
- 0x0a, 0xbf, 0xae, 0x2e, 0xd4, 0xbb, 0x8f, 0xa3, 0xa3, 0xfe, 0x6e, 0x01, 0xce, 0x06, 0xb8, 0x7d,
- 0x36, 0x57, 0xf3, 0x28, 0xdf, 0x38, 0xd8, 0xb4, 0x74, 0x31, 0xf2, 0x12, 0x61, 0x38, 0xf9, 0x30,
- 0xaf, 0xd5, 0x76, 0x5a, 0xb6, 0xeb, 0xcb, 0xc1, 0x5c, 0x61, 0xe0, 0x45, 0xd8, 0x87, 0xa1, 0x55,
- 0x18, 0x70, 0x29, 0x3d, 0x71, 0xd6, 0x1d, 0x72, 0x36, 0x98, 0x28, 0xcf, 0xfa, 0x8b, 0x39, 0x1a,
- 0xf4, 0xaa, 0xcc, 0xc3, 0x07, 0xf2, 0x1b, 0x2f, 0xe9, 0x48, 0xea, 0x81, 0x24, 0x1c, 0x5e, 0x7d,
- 0x74, 0x32, 0x16, 0xaa, 0xcb, 0x30, 0x29, 0x9c, 0x5a, 0xf9, 0xb6, 0xb1, 0x74, 0x82, 0xde, 0x1d,
- 0xd9, 0x19, 0xf7, 0xc7, 0x5c, 0x6a, 0xa6, 0xe3, 0xf5, 0xc3, 0x1d, 0xa3, 0xba, 0x30, 0x7c, 0x5d,
- 0x74, 0x12, 0xcd, 0x42, 0xc1, 0xf0, 0xd7, 0x02, 0x04, 0x8e, 0x42, 0xa5, 0x8c, 0x0b, 0x46, 0x17,
- 0x2f, 0x42, 0xe4, 0x63, 0xa9, 0xaf, 0xf3, 0xb1, 0xa4, 0x7e, 0xad, 0x00, 0xd3, 0x3e, 0x55, 0x7f,
- 0x8c, 0x65, 0x71, 0x5b, 0x7e, 0x80, 0x52, 0x74, 0xb0, 0xa9, 0xf1, 0x16, 0xf4, 0x33, 0x06, 0x98,
- 0xeb, 0x16, 0x3d, 0x40, 0x48, 0xbb, 0x83, 0x19, 0x22, 0xf4, 0x01, 0x18, 0x34, 0xa9, 0x86, 0xe1,
- 0x3f, 0xd5, 0xc8, 0x65, 0x98, 0x4d, 0x1b, 0x2e, 0x57, 0x5c, 0x44, 0x08, 0xb3, 0xe0, 0x22, 0x94,
- 0x17, 0x62, 0x41, 0x73, 0xf6, 0x31, 0x18, 0x95, 0xaa, 0x1d, 0x2a, 0x7e, 0xd9, 0xe7, 0x0a, 0x30,
- 0x73, 0x83, 0x98, 0xcd, 0x54, 0xd7, 0x87, 0x22, 0x0c, 0xe8, 0x5b, 0x9a, 0xc3, 0x43, 0xe3, 0x8d,
- 0xf1, 0x4d, 0x5e, 0xa2, 0x05, 0x98, 0x97, 0x53, 0x85, 0x23, 0xf2, 0x38, 0xed, 0x49, 0x69, 0x26,
- 0xc3, 0x98, 0x89, 0xef, 0x0f, 0x82, 0x2a, 0x86, 0x03, 0x8f, 0x54, 0xa0, 0xc7, 0xcb, 0x7b, 0x6b,
- 0xb7, 0x56, 0xd3, 0x9e, 0xa5, 0xa1, 0xbb, 0x30, 0x6e, 0xeb, 0x06, 0x26, 0x2d, 0xdb, 0x35, 0x3c,
- 0xdb, 0xd9, 0x15, 0x8b, 0x96, 0xeb, 0x68, 0xb9, 0x55, 0xaa, 0x84, 0x88, 0xf8, 0xf5, 0x61, 0xa4,
- 0x08, 0x47, 0x49, 0xa9, 0x5f, 0x54, 0x60, 0xf4, 0x86, 0xb1, 0x41, 0x1c, 0xee, 0xb7, 0xcb, 0x2c,
- 0x24, 0x91, 0x20, 0x6f, 0xa3, 0x69, 0x01, 0xde, 0xd0, 0x0e, 0x8c, 0x88, 0x73, 0x38, 0x78, 0x75,
- 0x78, 0x3d, 0x9f, 0xbf, 0x50, 0x40, 0x5a, 0x9c, 0x6f, 0xd2, 0x87, 0xef, 0x97, 0xb8, 0x38, 0x24,
- 0xa6, 0xbe, 0x0a, 0xa7, 0x53, 0x1a, 0xd1, 0x85, 0x64, 0xae, 0xab, 0xe2, 0xa3, 0xf1, 0xb9, 0x15,
- 0x5d, 0x48, 0x56, 0x8e, 0xce, 0x43, 0x1f, 0xb1, 0xea, 0xe2, 0x8b, 0x19, 0xda, 0xdf, 0x2b, 0xf6,
- 0x2d, 0x5a, 0x75, 0x4c, 0xcb, 0x28, 0x13, 0x37, 0xed, 0x88, 0xc4, 0xc6, 0x98, 0xf8, 0xb2, 0x28,
- 0xc3, 0x01, 0x94, 0x79, 0x78, 0xc5, 0x9d, 0x99, 0xa8, 0x66, 0x31, 0xb9, 0x19, 0xe3, 0x2d, 0xbd,
- 0xf8, 0x50, 0xc5, 0xf9, 0xd4, 0xc2, 0x8c, 0x98, 0x90, 0x04, 0xc7, 0xc3, 0x09, 0xba, 0xea, 0x2f,
- 0xf7, 0xc3, 0xa5, 0x1b, 0xb6, 0x63, 0xdc, 0xb5, 0x2d, 0x4f, 0x33, 0xab, 0x76, 0x3d, 0xf4, 0x6f,
- 0x15, 0x47, 0xd6, 0xc7, 0x14, 0x38, 0xa7, 0xb7, 0xda, 0x5c, 0x33, 0xf1, 0x5d, 0x44, 0xab, 0xc4,
- 0x31, 0xec, 0xbc, 0x0f, 0x35, 0x98, 0x3b, 0x6f, 0xa9, 0xba, 0x9e, 0x86, 0x12, 0x67, 0xd1, 0x62,
- 0xef, 0x45, 0xea, 0xf6, 0x1d, 0x8b, 0x75, 0xae, 0xe6, 0xb1, 0xd9, 0xbc, 0x1b, 0x2e, 0x42, 0xce,
- 0xf7, 0x22, 0xe5, 0x54, 0x8c, 0x38, 0x83, 0x12, 0xfa, 0x10, 0x9c, 0x31, 0x78, 0xe7, 0x30, 0xd1,
- 0xea, 0x86, 0x45, 0x5c, 0x97, 0x3b, 0x9b, 0xf7, 0xf0, 0x20, 0xa2, 0x92, 0x86, 0x10, 0xa7, 0xd3,
- 0x41, 0x2f, 0x01, 0xb8, 0xbb, 0x96, 0x2e, 0xe6, 0x3f, 0x9f, 0x23, 0x2a, 0x17, 0x91, 0x03, 0x2c,
- 0x58, 0xc2, 0x48, 0x15, 0x2d, 0x2f, 0xd8, 0x94, 0x83, 0xcc, 0x99, 0x98, 0x29, 0x5a, 0xe1, 0x1e,
- 0x0a, 0xe1, 0xea, 0xa7, 0x14, 0x98, 0xa8, 0x58, 0x55, 0x53, 0xd3, 0x09, 0xf7, 0xab, 0x74, 0xd1,
- 0x35, 0x18, 0x71, 0x83, 0x1b, 0x19, 0xce, 0x11, 0xc2, 0xef, 0x33, 0xb8, 0x8b, 0x09, 0xeb, 0x30,
- 0x2f, 0x6d, 0xc3, 0x12, 0x87, 0xdd, 0x92, 0xed, 0x70, 0x44, 0xe2, 0xbb, 0xe3, 0x5e, 0xda, 0x49,
- 0x30, 0x4e, 0x6b, 0xa3, 0xfe, 0x9c, 0x02, 0xd3, 0xd1, 0xee, 0x08, 0x97, 0x86, 0x1f, 0x55, 0x60,
- 0x3a, 0xf2, 0x98, 0x5a, 0x80, 0x7b, 0x89, 0xef, 0x54, 0x4d, 0xc1, 0xc7, 0x5d, 0x7c, 0xd3, 0x20,
- 0x38, 0x95, 0xbe, 0xfa, 0xb3, 0x0a, 0x0c, 0x89, 0x58, 0x8f, 0xe8, 0xad, 0x31, 0xeb, 0x79, 0x70,
- 0xb4, 0xc5, 0x2c, 0xe8, 0xbb, 0xcc, 0x3f, 0x43, 0x1c, 0x4d, 0xe2, 0x94, 0xc9, 0x65, 0x7e, 0x15,
- 0x84, 0xc3, 0x73, 0x2e, 0xe2, 0xa7, 0xe1, 0x5f, 0xcd, 0x48, 0xc4, 0xd4, 0xd7, 0x14, 0x98, 0x4a,
- 0xb4, 0xea, 0x42, 0x1c, 0x3d, 0x41, 0x8f, 0xd5, 0x2f, 0xf7, 0xd3, 0x2d, 0xe9, 0x51, 0x7e, 0x6f,
- 0x72, 0xc3, 0xf6, 0x09, 0xe8, 0xbf, 0x0f, 0xc2, 0x88, 0xd1, 0x6c, 0xb6, 0x3d, 0x76, 0x89, 0x38,
- 0x10, 0x5a, 0x8b, 0x2b, 0x7e, 0x21, 0x0e, 0xe1, 0xc8, 0x12, 0x92, 0x16, 0x3f, 0x05, 0x97, 0xf3,
- 0xad, 0x9c, 0x3c, 0xc0, 0x39, 0x2a, 0x15, 0x71, 0x71, 0x28, 0x4d, 0x10, 0xfb, 0x1e, 0x05, 0xc0,
- 0xf5, 0x1c, 0xc3, 0x6a, 0xd0, 0x42, 0x21, 0x8d, 0xe1, 0x23, 0x20, 0x5b, 0x0b, 0x90, 0x72, 0xe2,
- 0x61, 0xfc, 0xc7, 0x00, 0x80, 0x25, 0xca, 0x68, 0x5e, 0x08, 0xa1, 0xfc, 0xc8, 0x7c, 0x7b, 0x4c,
- 0xdc, 0xbe, 0x94, 0xe2, 0x09, 0xcb, 0x09, 0x85, 0x52, 0xea, 0xec, 0xa3, 0x30, 0x12, 0xd0, 0x3b,
- 0x48, 0xa8, 0x1b, 0x93, 0x84, 0xba, 0xd9, 0x27, 0xe0, 0x54, 0xac, 0xbb, 0x87, 0x92, 0x09, 0xff,
- 0x54, 0x01, 0x14, 0x1d, 0xfd, 0x09, 0x58, 0x0e, 0x1a, 0x51, 0xcb, 0xc1, 0x42, 0xef, 0x4b, 0x96,
- 0x61, 0x3a, 0xf8, 0x69, 0x04, 0x2c, 0x14, 0x6e, 0x10, 0x1a, 0x5a, 0x9c, 0xfc, 0x54, 0x50, 0x09,
- 0x5f, 0x80, 0x8b, 0x2f, 0xb7, 0x07, 0x41, 0xe5, 0x66, 0x0c, 0x57, 0x28, 0xa8, 0xc4, 0x21, 0x38,
- 0x41, 0x17, 0x7d, 0x42, 0x81, 0x49, 0x2d, 0x1a, 0x0a, 0xd7, 0x9f, 0x99, 0x5c, 0x01, 0xba, 0x62,
- 0x61, 0x75, 0xc3, 0xbe, 0xc4, 0x00, 0x2e, 0x4e, 0x90, 0x45, 0x8f, 0xc0, 0x98, 0xd6, 0x32, 0xe6,
- 0xdb, 0x75, 0x83, 0x6a, 0x9e, 0x7e, 0xc4, 0x50, 0x66, 0x0d, 0x99, 0xaf, 0x56, 0x82, 0x72, 0x1c,
- 0xa9, 0x15, 0xc4, 0x9c, 0x2d, 0x85, 0x8e, 0xc3, 0xbd, 0xc4, 0x9c, 0x15, 0x73, 0x18, 0xc6, 0x9c,
- 0x15, 0x53, 0x27, 0x13, 0x41, 0x16, 0x80, 0x6d, 0xd4, 0x75, 0x41, 0x72, 0x30, 0xff, 0x1d, 0xc8,
- 0xad, 0x4a, 0xb9, 0x24, 0x28, 0x32, 0xf1, 0x21, 0xfc, 0x8d, 0x25, 0x0a, 0xe8, 0xd3, 0x0a, 0x8c,
- 0x0b, 0xde, 0x2d, 0x68, 0x0e, 0xb1, 0x25, 0x7a, 0x21, 0xef, 0x7e, 0x89, 0xed, 0xc9, 0x39, 0x2c,
- 0x23, 0xe7, 0x7c, 0x27, 0x08, 0x20, 0x10, 0x81, 0xe1, 0x68, 0x3f, 0x98, 0x0c, 0xe0, 0x46, 0x2e,
- 0xa1, 0x44, 0x07, 0x87, 0xf3, 0xcb, 0x00, 0xb5, 0x14, 0x7c, 0xe2, 0x91, 0x51, 0x0a, 0x04, 0xa7,
- 0xd2, 0xa7, 0x72, 0xed, 0xa9, 0x3b, 0x9a, 0xa7, 0x6f, 0x95, 0x34, 0x7d, 0x8b, 0xdd, 0x41, 0xf2,
- 0xe7, 0x94, 0x39, 0xf7, 0xf5, 0x73, 0x51, 0x54, 0x0b, 0xa7, 0xf7, 0xf7, 0x8a, 0xa7, 0x62, 0x85,
- 0x38, 0x4e, 0x10, 0xd9, 0x30, 0xec, 0x88, 0x78, 0xf0, 0xe2, 0x05, 0x7c, 0xbe, 0x10, 0xe8, 0xf1,
- 0xe0, 0xf2, 0x5c, 0x33, 0xf2, 0x7f, 0xe1, 0x80, 0x08, 0x6a, 0xc0, 0x25, 0xae, 0x1b, 0xce, 0x5b,
- 0xb6, 0xb5, 0xdb, 0xb4, 0xdb, 0xee, 0x7c, 0xdb, 0xdb, 0x22, 0x96, 0xe7, 0x9b, 0xc2, 0x47, 0xd9,
- 0x31, 0xca, 0x1e, 0xcd, 0x2d, 0x76, 0xaa, 0x88, 0x3b, 0xe3, 0x41, 0xcf, 0xc3, 0x30, 0xbb, 0xa7,
- 0x5b, 0x5b, 0x5b, 0x66, 0x2f, 0x33, 0x0f, 0x2f, 0x2e, 0xb3, 0x21, 0x2c, 0x0a, 0x1c, 0x38, 0xc0,
- 0x86, 0x6e, 0xc3, 0x90, 0xc9, 0x03, 0xfa, 0xb3, 0x17, 0x9a, 0x39, 0x99, 0x62, 0x3c, 0x39, 0x00,
- 0x57, 0xa0, 0xc5, 0x0f, 0xec, 0x53, 0x40, 0x2d, 0xb8, 0x52, 0x27, 0x9b, 0x5a, 0xdb, 0xf4, 0x56,
- 0x6d, 0x0f, 0xb3, 0x17, 0x6a, 0x81, 0xc5, 0xd3, 0x7f, 0x84, 0x3b, 0xc1, 0x62, 0xb0, 0xb1, 0xb7,
- 0x7f, 0xe5, 0x03, 0xea, 0xe2, 0x03, 0xb1, 0xa1, 0x5d, 0xb8, 0x4f, 0xd4, 0x61, 0x4f, 0xe2, 0xf4,
- 0x2d, 0x3a, 0xcb, 0x49, 0xa2, 0xa7, 0x18, 0xd1, 0x6f, 0xda, 0xdf, 0x2b, 0xde, 0x57, 0x3e, 0xb8,
- 0x3a, 0xee, 0x06, 0x27, 0x7b, 0x65, 0x44, 0x62, 0x57, 0x40, 0x33, 0x93, 0xf9, 0xe7, 0x38, 0x7e,
- 0x9d, 0xc4, 0xdd, 0xe1, 0xe2, 0xa5, 0x38, 0x41, 0x13, 0x7d, 0x41, 0x81, 0x19, 0xd7, 0x73, 0xda,
- 0xba, 0xd7, 0x76, 0x48, 0x3d, 0xb6, 0x43, 0xa7, 0x58, 0x87, 0x72, 0x09, 0x70, 0xb5, 0x0c, 0x9c,
- 0xec, 0x39, 0xf8, 0x4c, 0x16, 0x14, 0x67, 0xf6, 0x05, 0x7d, 0x5e, 0x81, 0x73, 0x51, 0x20, 0xd5,
- 0xe9, 0x79, 0x3f, 0x51, 0xfe, 0x4b, 0x96, 0x5a, 0x3a, 0x4a, 0xae, 0xc1, 0x67, 0x00, 0x71, 0x56,
- 0x47, 0xe2, 0x37, 0xe3, 0xa7, 0x4f, 0xf8, 0x66, 0x7c, 0xf6, 0x69, 0x40, 0xc9, 0xe3, 0xe3, 0x20,
- 0x39, 0x70, 0x58, 0x96, 0x03, 0x3f, 0x3b, 0x00, 0x17, 0xe8, 0xa9, 0x14, 0x6a, 0x3f, 0x2b, 0x9a,
- 0xa5, 0x35, 0x5e, 0x9f, 0x12, 0xd3, 0x17, 0x15, 0x38, 0xb7, 0x95, 0x6e, 0xda, 0x11, 0xfa, 0xd7,
- 0x33, 0xb9, 0x4c, 0x70, 0x9d, 0xac, 0x45, 0x9c, 0x61, 0x77, 0xac, 0x82, 0xb3, 0x3a, 0x85, 0x9e,
- 0x86, 0x49, 0xcb, 0xae, 0x93, 0x52, 0xa5, 0x8c, 0x57, 0x34, 0xf7, 0x76, 0xcd, 0x77, 0xd4, 0x19,
- 0xe0, 0xdf, 0xeb, 0x6a, 0x0c, 0x86, 0x13, 0xb5, 0xd1, 0x36, 0xa0, 0x96, 0x5d, 0x5f, 0xdc, 0xe6,
- 0x89, 0x2f, 0x7a, 0x73, 0x99, 0x65, 0xce, 0x02, 0xd5, 0x04, 0x36, 0x9c, 0x42, 0x81, 0xd9, 0xa6,
- 0x68, 0x67, 0x56, 0x6c, 0xcb, 0xf0, 0x6c, 0x87, 0x05, 0x38, 0xe8, 0xc9, 0x44, 0xc3, 0x6c, 0x53,
- 0xab, 0xa9, 0x18, 0x71, 0x06, 0x25, 0xf5, 0xbf, 0x2b, 0x70, 0x8a, 0x6e, 0x8b, 0xaa, 0x63, 0xef,
- 0xec, 0xbe, 0x1e, 0x37, 0xe4, 0x03, 0xc2, 0x67, 0x91, 0xdb, 0x76, 0xce, 0x48, 0xfe, 0x8a, 0x23,
- 0xac, 0xcf, 0xa1, 0x8b, 0xa2, 0x6c, 0x56, 0xee, 0xcb, 0x36, 0x2b, 0xab, 0x9f, 0x2e, 0x70, 0xcd,
- 0xc5, 0x37, 0xeb, 0xbe, 0x2e, 0xbf, 0xc3, 0x47, 0x61, 0x9c, 0x96, 0xad, 0x68, 0x3b, 0xd5, 0xf2,
- 0xb3, 0xb6, 0xe9, 0xbf, 0xc6, 0x66, 0xb6, 0xf6, 0x9b, 0x32, 0x00, 0x47, 0xeb, 0xa1, 0xc7, 0x61,
- 0xa8, 0xc5, 0xe3, 0x84, 0x09, 0x9d, 0xf9, 0x0a, 0x77, 0xec, 0x63, 0x45, 0xf7, 0xf6, 0x8a, 0x53,
- 0xe1, 0x15, 0xaf, 0x1f, 0xad, 0xcc, 0x6f, 0xa0, 0xfe, 0xf2, 0x59, 0x60, 0xc8, 0x4d, 0xe2, 0xbd,
- 0x1e, 0xe7, 0xe4, 0x21, 0x18, 0xd5, 0x5b, 0xed, 0xd2, 0x52, 0xed, 0x99, 0xb6, 0xcd, 0x6c, 0x21,
- 0x2c, 0x3f, 0x0c, 0xe5, 0xde, 0xa5, 0xea, 0xba, 0x5f, 0x8c, 0xe5, 0x3a, 0x94, 0x3b, 0xe8, 0xad,
- 0xb6, 0xe0, 0xb7, 0x55, 0xf9, 0xbd, 0x0a, 0xe3, 0x0e, 0xa5, 0xea, 0x7a, 0x04, 0x86, 0x13, 0xb5,
- 0xd1, 0x87, 0x60, 0x8c, 0x88, 0x0f, 0xf7, 0x86, 0xe6, 0xd4, 0x05, 0x5f, 0xa8, 0xe4, 0x1d, 0x7c,
- 0x30, 0xb5, 0x3e, 0x37, 0xe0, 0x1a, 0xe0, 0xa2, 0x44, 0x02, 0x47, 0x08, 0xa2, 0x17, 0xe1, 0xbc,
- 0xff, 0x9b, 0xae, 0xb2, 0x5d, 0x8f, 0x33, 0x8a, 0x01, 0xee, 0x36, 0xb3, 0x98, 0x55, 0x09, 0x67,
- 0xb7, 0x47, 0x3f, 0xa3, 0xc0, 0xd9, 0x00, 0x6a, 0x58, 0x46, 0xb3, 0xdd, 0xc4, 0x44, 0x37, 0x35,
- 0xa3, 0x29, 0xf4, 0xbe, 0xe7, 0x8e, 0x6c, 0xa0, 0x51, 0xf4, 0x9c, 0x59, 0xa5, 0xc3, 0x70, 0x46,
- 0x97, 0xd0, 0x6b, 0x0a, 0x5c, 0xf1, 0x41, 0x55, 0x87, 0xb8, 0x6e, 0xdb, 0x21, 0x61, 0x2c, 0x00,
- 0x31, 0x25, 0x43, 0xb9, 0x78, 0x27, 0x13, 0x80, 0x17, 0x0f, 0xc0, 0x8d, 0x0f, 0xa4, 0x2e, 0x6f,
- 0x97, 0x9a, 0xbd, 0xe9, 0x09, 0x45, 0xf1, 0xb8, 0xb6, 0x0b, 0x25, 0x81, 0x23, 0x04, 0xd1, 0xcf,
- 0x29, 0x70, 0x4e, 0x2e, 0x90, 0x77, 0x0b, 0xd7, 0x10, 0x9f, 0x3f, 0xb2, 0xce, 0xc4, 0xf0, 0x73,
- 0x09, 0x2f, 0x03, 0x88, 0xb3, 0x7a, 0x45, 0xd9, 0x76, 0x93, 0x6d, 0x4c, 0xae, 0x45, 0x0e, 0x70,
- 0xb6, 0xcd, 0xf7, 0xaa, 0x8b, 0x7d, 0x18, 0x7a, 0x04, 0xc6, 0x5a, 0x76, 0xbd, 0x6a, 0xd4, 0x5d,
- 0x16, 0xc3, 0x8c, 0xe9, 0x7a, 0x7d, 0x7c, 0x3a, 0xaa, 0x76, 0xbd, 0x5a, 0x29, 0xf3, 0x72, 0x1c,
- 0xa9, 0x85, 0xe6, 0x00, 0x36, 0x35, 0xc3, 0xac, 0xdd, 0xd1, 0x5a, 0xb7, 0xfc, 0xa0, 0x38, 0xcc,
- 0x16, 0xb1, 0x14, 0x94, 0x62, 0xa9, 0x06, 0x5d, 0x3f, 0xca, 0x77, 0x30, 0xe1, 0x61, 0xa7, 0x99,
- 0x7a, 0x74, 0x14, 0xeb, 0xe7, 0x23, 0xe4, 0x1d, 0xbe, 0x29, 0x91, 0xc0, 0x11, 0x82, 0xe8, 0x63,
- 0x0a, 0x4c, 0xb8, 0xbb, 0xae, 0x47, 0x9a, 0x41, 0x1f, 0x4e, 0x1d, 0x75, 0x1f, 0x98, 0x4d, 0xbc,
- 0x16, 0x21, 0x82, 0x63, 0x44, 0x59, 0x78, 0xa1, 0xa6, 0xd6, 0x20, 0xd7, 0x4b, 0x37, 0x8c, 0xc6,
- 0x56, 0x10, 0xdd, 0xa5, 0x4a, 0x1c, 0x9d, 0x58, 0x1e, 0x53, 0xac, 0x06, 0x44, 0x78, 0xa1, 0xec,
- 0x6a, 0xb8, 0x13, 0x0e, 0xf4, 0x12, 0xcc, 0x0a, 0xf0, 0xb2, 0x7d, 0x27, 0x41, 0x81, 0x47, 0xf1,
- 0x61, 0x0e, 0x90, 0x95, 0xcc, 0x5a, 0xb8, 0x03, 0x06, 0x54, 0x81, 0xd3, 0x2e, 0x71, 0xd8, 0x9d,
- 0x20, 0x8f, 0x08, 0x59, 0x6d, 0x9b, 0xa6, 0xcb, 0x54, 0x1b, 0xf1, 0xe4, 0xa7, 0x96, 0x04, 0xe3,
- 0xb4, 0x36, 0xe8, 0x89, 0xe0, 0x59, 0xf0, 0x2e, 0x2d, 0x78, 0xa6, 0x5a, 0x63, 0x9a, 0xc8, 0x00,
- 0xb7, 0x94, 0xe0, 0x28, 0x08, 0xc7, 0xeb, 0xd2, 0xd3, 0xdc, 0x2f, 0x5a, 0x68, 0x3b, 0xae, 0x37,
- 0x33, 0xcd, 0x1a, 0xb3, 0xd3, 0x1c, 0xcb, 0x00, 0x1c, 0xad, 0x87, 0x1e, 0x87, 0x09, 0x97, 0xe8,
- 0xba, 0xdd, 0x6c, 0x09, 0x3d, 0x79, 0xe6, 0x0c, 0xeb, 0x3d, 0x5f, 0xc1, 0x08, 0x04, 0xc7, 0x6a,
- 0xa2, 0x5d, 0x38, 0x1d, 0x84, 0xd0, 0x5d, 0xb6, 0x1b, 0x2b, 0xda, 0x0e, 0x13, 0x8e, 0xcf, 0xe6,
- 0x09, 0xf1, 0xc0, 0xa7, 0xab, 0x94, 0x44, 0x87, 0xd3, 0x68, 0xa0, 0x65, 0x98, 0x8e, 0x15, 0x2f,
- 0x19, 0x26, 0x71, 0x67, 0xce, 0xb1, 0x61, 0x33, 0x63, 0x57, 0x29, 0x05, 0x8e, 0x53, 0x5b, 0xa1,
- 0x5b, 0x70, 0xa6, 0xe5, 0xd8, 0x1e, 0xd1, 0xbd, 0x9b, 0x54, 0x20, 0x30, 0xc5, 0x00, 0xdd, 0x99,
- 0x19, 0x36, 0x17, 0xec, 0x3e, 0xb4, 0x9a, 0x56, 0x01, 0xa7, 0xb7, 0x43, 0x9f, 0x55, 0xe0, 0xb2,
- 0xeb, 0x39, 0x44, 0x6b, 0x1a, 0x56, 0xa3, 0x64, 0x5b, 0x16, 0x61, 0x8c, 0xa9, 0x52, 0x0f, 0x5f,
- 0xcc, 0x9d, 0xcf, 0x75, 0x8a, 0xa8, 0xfb, 0x7b, 0xc5, 0xcb, 0xb5, 0x8e, 0x98, 0xf1, 0x01, 0x94,
- 0xd1, 0xab, 0x00, 0x4d, 0xd2, 0xb4, 0x9d, 0x5d, 0xca, 0x91, 0x66, 0x66, 0xf3, 0xeb, 0xbb, 0x2b,
- 0x01, 0x16, 0xfe, 0xf9, 0x47, 0x6e, 0x72, 0x43, 0x20, 0x96, 0xc8, 0xd1, 0xa9, 0xa6, 0xfc, 0x56,
- 0x44, 0xb1, 0x92, 0x3e, 0x9a, 0x0b, 0x6c, 0xe5, 0xd8, 0x54, 0xaf, 0xa4, 0x55, 0xc0, 0xe9, 0xed,
- 0x90, 0x0b, 0x53, 0xec, 0x0b, 0x15, 0x27, 0xf9, 0xf5, 0xd2, 0x7c, 0x83, 0xcc, 0x5c, 0xcc, 0x35,
- 0xb9, 0x54, 0xf6, 0x9f, 0xaa, 0xc4, 0x91, 0xe1, 0x24, 0xfe, 0x90, 0xa8, 0xb6, 0x13, 0x12, 0xbd,
- 0xd4, 0x2b, 0x51, 0x09, 0x19, 0x4e, 0xe2, 0x57, 0xf7, 0x0a, 0x70, 0x26, 0xf5, 0x94, 0xa4, 0xcc,
- 0x83, 0x4f, 0xf1, 0xbc, 0x9f, 0xff, 0x4b, 0x5c, 0x7b, 0x32, 0xe6, 0xb1, 0x12, 0x05, 0xe1, 0x78,
- 0x5d, 0x2a, 0xc3, 0x32, 0x6a, 0x4b, 0xb5, 0xb0, 0x7d, 0x21, 0x94, 0x61, 0x2b, 0x31, 0x18, 0x4e,
- 0xd4, 0x46, 0x25, 0x31, 0x1f, 0x4b, 0xb5, 0x0a, 0x55, 0x03, 0xdd, 0x25, 0x87, 0xf8, 0xda, 0x41,
- 0x38, 0x3e, 0x19, 0x88, 0x93, 0xf5, 0xe9, 0x28, 0xe8, 0x0f, 0xb9, 0x17, 0xfd, 0xe1, 0x28, 0x56,
- 0xa3, 0x20, 0x1c, 0xaf, 0xeb, 0xeb, 0xe9, 0x91, 0x2e, 0x0c, 0x84, 0xa3, 0x58, 0x8d, 0xc1, 0x70,
- 0xa2, 0xb6, 0xfa, 0x67, 0xfd, 0x70, 0x5f, 0x17, 0x92, 0x25, 0x6a, 0xa6, 0x4f, 0xf7, 0xe1, 0x79,
- 0x5e, 0x77, 0xcb, 0xd3, 0xca, 0x58, 0x9e, 0xc3, 0xd3, 0xeb, 0x76, 0x39, 0xdd, 0xac, 0xe5, 0x3c,
- 0x3c, 0xc9, 0xee, 0x97, 0xbf, 0x99, 0xbe, 0xfc, 0x39, 0x67, 0xf5, 0xc0, 0xed, 0xd2, 0xca, 0xd8,
- 0x2e, 0x39, 0x67, 0xb5, 0x8b, 0xed, 0xf5, 0xe7, 0xfd, 0x70, 0x7f, 0x37, 0x52, 0x6e, 0xce, 0xfd,
- 0x95, 0xc2, 0x5b, 0x8e, 0x75, 0x7f, 0x65, 0xbd, 0xe7, 0x3e, 0xc6, 0xfd, 0xd5, 0x91, 0x7d, 0x1e,
- 0xcf, 0xfe, 0xca, 0x9a, 0xd5, 0xe3, 0xda, 0x5f, 0x59, 0xb3, 0xda, 0xc5, 0xfe, 0xfa, 0x9b, 0xf8,
- 0xf9, 0x10, 0x88, 0xda, 0x15, 0xe8, 0xd3, 0x5b, 0xed, 0x9c, 0x4c, 0x8a, 0x79, 0x19, 0x96, 0xaa,
- 0xeb, 0x98, 0xe2, 0x40, 0x18, 0x06, 0xf9, 0xfe, 0xc9, 0xc9, 0x82, 0x98, 0xe7, 0x28, 0xdf, 0x92,
- 0x58, 0x60, 0xa2, 0x53, 0x45, 0x5a, 0x5b, 0xa4, 0x49, 0x1c, 0xcd, 0xac, 0x79, 0xb6, 0xa3, 0x35,
- 0xf2, 0x72, 0x1b, 0x7e, 0x83, 0x12, 0xc3, 0x85, 0x13, 0xd8, 0xe9, 0x84, 0xb4, 0x8c, 0x7a, 0x4e,
- 0xfe, 0xc2, 0x26, 0xa4, 0x5a, 0x29, 0x63, 0x8a, 0x43, 0xfd, 0xb5, 0x61, 0x90, 0x82, 0xd3, 0xa3,
- 0x4f, 0x2a, 0x30, 0xa5, 0xc7, 0x63, 0x72, 0xf6, 0xe2, 0x0f, 0x95, 0x08, 0xf0, 0xc9, 0xb7, 0x7c,
- 0xa2, 0x18, 0x27, 0xc9, 0xa2, 0x0f, 0x2b, 0xdc, 0xc8, 0x17, 0xdc, 0xe6, 0x89, 0x69, 0xbd, 0x7e,
- 0x44, 0xf7, 0xde, 0xa1, 0xb5, 0x30, 0xbc, 0x62, 0x8d, 0x12, 0x44, 0xaf, 0x29, 0x70, 0xe6, 0x76,
- 0xda, 0xdd, 0x84, 0x98, 0xfc, 0x5b, 0x79, 0xbb, 0x92, 0x71, 0xd9, 0xc1, 0x25, 0xc8, 0xd4, 0x0a,
- 0x38, 0xbd, 0x23, 0xc1, 0x2c, 0x05, 0xe6, 0x5a, 0xf1, 0x9d, 0xe6, 0x9e, 0xa5, 0x98, 0xdd, 0x37,
- 0x9c, 0xa5, 0x00, 0x80, 0xa3, 0x04, 0x51, 0x0b, 0x46, 0x6e, 0xfb, 0x36, 0x72, 0x61, 0x17, 0x2b,
- 0xe5, 0xa5, 0x2e, 0x19, 0xda, 0xb9, 0xbf, 0x57, 0x50, 0x88, 0x43, 0x22, 0x68, 0x0b, 0x86, 0x6e,
- 0x73, 0x5e, 0x21, 0xec, 0x59, 0xf3, 0x3d, 0x6b, 0xff, 0xdc, 0xac, 0x22, 0x8a, 0xb0, 0x8f, 0x5e,
- 0x7e, 0x4b, 0x30, 0x7c, 0xc0, 0x13, 0xb7, 0xcf, 0x2a, 0x70, 0x66, 0x9b, 0x38, 0x9e, 0xa1, 0xc7,
- 0x6f, 0x86, 0x46, 0xf2, 0x5b, 0x28, 0x9e, 0x4d, 0x43, 0xc8, 0xb7, 0x49, 0x2a, 0x08, 0xa7, 0x77,
- 0x01, 0x3d, 0x0b, 0xfd, 0xc4, 0xd3, 0xeb, 0x22, 0x80, 0xf3, 0xbb, 0xf3, 0x3e, 0xd9, 0xe5, 0xef,
- 0x5e, 0xe8, 0x7f, 0x98, 0xe1, 0x53, 0xff, 0x4a, 0x81, 0x84, 0x6d, 0x1a, 0xfd, 0x80, 0x02, 0x63,
- 0x9b, 0x44, 0xf3, 0xda, 0x0e, 0xb9, 0x2e, 0x7c, 0x42, 0xfb, 0xae, 0x8e, 0x3e, 0xfc, 0xec, 0x51,
- 0x98, 0xc4, 0xe7, 0x96, 0x24, 0xc4, 0xdc, 0x59, 0x25, 0x48, 0x38, 0x21, 0x83, 0x70, 0xa4, 0x07,
- 0xb3, 0x4f, 0xc1, 0x54, 0xa2, 0xe1, 0xa1, 0xae, 0x29, 0x7f, 0x55, 0x81, 0xb4, 0xdc, 0xe6, 0xe8,
- 0x25, 0x18, 0xd0, 0xea, 0xf5, 0x20, 0xc5, 0xe5, 0x63, 0xf9, 0xfc, 0xa6, 0xea, 0x72, 0xa4, 0x20,
- 0xf6, 0x13, 0x73, 0xb4, 0x68, 0x09, 0x90, 0x16, 0xb9, 0x97, 0x5e, 0x09, 0x43, 0x54, 0xb0, 0xeb,
- 0xb4, 0xf9, 0x04, 0x14, 0xa7, 0xb4, 0x50, 0x3f, 0xae, 0x00, 0x4a, 0xa6, 0x28, 0x41, 0x0e, 0x0c,
- 0x8b, 0xfd, 0xeb, 0xaf, 0x52, 0x39, 0xe7, 0x6b, 0xba, 0xc8, 0xd3, 0xd0, 0xd0, 0x09, 0x4f, 0x14,
- 0xb8, 0x38, 0xa0, 0xa3, 0xfe, 0x9d, 0x02, 0x61, 0x1a, 0x3c, 0xf4, 0x4e, 0x18, 0xad, 0x13, 0x57,
- 0x77, 0x8c, 0x96, 0x17, 0x3e, 0x24, 0x0d, 0x1e, 0xa4, 0x95, 0x43, 0x10, 0x96, 0xeb, 0x21, 0x15,
- 0x06, 0x3d, 0xcd, 0xbd, 0x5d, 0x29, 0x0b, 0x65, 0x8f, 0x1d, 0xcd, 0x6b, 0xac, 0x04, 0x0b, 0x48,
- 0x18, 0x3a, 0xb6, 0xaf, 0x8b, 0xd0, 0xb1, 0x68, 0xf3, 0x08, 0xe2, 0xe4, 0xa2, 0x83, 0x63, 0xe4,
- 0xaa, 0x3f, 0x55, 0x80, 0x53, 0xb4, 0xca, 0x8a, 0x66, 0x58, 0x1e, 0xb1, 0xd8, 0xb3, 0xa9, 0x9c,
- 0x93, 0xd0, 0x80, 0x71, 0x2f, 0xf2, 0x68, 0xf9, 0xf0, 0x8f, 0x6a, 0x03, 0x4f, 0xaf, 0xe8, 0x53,
- 0xe5, 0x28, 0x5e, 0xf4, 0x98, 0xff, 0x6e, 0x8d, 0xab, 0xc5, 0xf7, 0xf9, 0x5b, 0x95, 0x3d, 0x46,
- 0xbb, 0x27, 0x5e, 0x80, 0x07, 0xb9, 0x13, 0x23, 0x4f, 0xd4, 0x1e, 0x85, 0x71, 0xf1, 0x42, 0x82,
- 0xc7, 0x00, 0x16, 0x6a, 0x31, 0x3b, 0x56, 0x96, 0x64, 0x00, 0x8e, 0xd6, 0x53, 0xff, 0xb0, 0x00,
- 0xd1, 0x0c, 0x8d, 0x79, 0x67, 0x29, 0x19, 0x00, 0xb9, 0x70, 0x6c, 0x01, 0x90, 0x79, 0x8e, 0x72,
- 0xe6, 0xce, 0x2d, 0xee, 0xd9, 0xe5, 0xfc, 0xc4, 0xac, 0x1c, 0x07, 0x35, 0xc2, 0x69, 0xed, 0x3f,
- 0xf4, 0xb4, 0xbe, 0x53, 0x78, 0xfe, 0x0e, 0x44, 0xc2, 0x50, 0xfb, 0x9e, 0xbf, 0x53, 0x91, 0x86,
- 0xd2, 0x2b, 0xbb, 0x79, 0x10, 0x39, 0x4e, 0xe8, 0xba, 0x88, 0x10, 0xd9, 0xee, 0x9a, 0xed, 0x69,
- 0x26, 0x9b, 0x4e, 0x61, 0x74, 0x5d, 0x91, 0x01, 0x38, 0x5a, 0x4f, 0x5d, 0x85, 0x37, 0x2f, 0xdb,
- 0x5a, 0x7d, 0x41, 0x33, 0xe9, 0xd6, 0x75, 0x84, 0x5b, 0x9e, 0xcb, 0x4e, 0xe6, 0xaa, 0x63, 0x7b,
- 0xb6, 0x6e, 0x9b, 0xf4, 0xdc, 0xd4, 0x82, 0x58, 0xc1, 0xec, 0x22, 0xd2, 0x3f, 0x37, 0x45, 0xac,
- 0x5d, 0xec, 0xc3, 0xd5, 0xdf, 0x56, 0x60, 0x48, 0xe4, 0x3d, 0xe9, 0xe2, 0x61, 0xe9, 0x26, 0x0c,
- 0x30, 0xed, 0xa8, 0x17, 0xa9, 0xb4, 0xb6, 0x65, 0xdb, 0x5e, 0x24, 0x61, 0x12, 0x4f, 0x39, 0xc6,
- 0x92, 0x44, 0x72, 0xf4, 0xcc, 0x1f, 0xd5, 0xd1, 0xb7, 0x0c, 0x8f, 0x30, 0xb7, 0x1b, 0xb1, 0xf1,
- 0xb9, 0x3f, 0xaa, 0x54, 0x8e, 0x23, 0xb5, 0xd4, 0xff, 0x36, 0x00, 0x57, 0xfc, 0x1c, 0x2e, 0x71,
- 0x51, 0x2d, 0xe0, 0xb9, 0xbb, 0x41, 0x52, 0x19, 0x16, 0x14, 0xdf, 0xb7, 0xa9, 0xe6, 0xd3, 0x92,
- 0xcf, 0x49, 0x69, 0x63, 0x64, 0x74, 0x38, 0x8d, 0x06, 0x8f, 0xbe, 0xce, 0x8a, 0x6f, 0x10, 0xcd,
- 0xf4, 0xb6, 0x7c, 0xda, 0x85, 0x5e, 0xa2, 0xaf, 0x27, 0xf1, 0xe1, 0x54, 0x2a, 0xcc, 0xa5, 0xc3,
- 0x4f, 0x66, 0xe3, 0x10, 0x4d, 0xf6, 0x27, 0xe9, 0xe1, 0xb9, 0xd1, 0x4a, 0x2a, 0x46, 0x9c, 0x41,
- 0x89, 0x99, 0x1b, 0xb5, 0x1d, 0x66, 0xbd, 0xc0, 0xc4, 0x73, 0x0c, 0x96, 0xf8, 0x2a, 0xb8, 0xab,
- 0x58, 0x89, 0x82, 0x70, 0xbc, 0x2e, 0x7a, 0x1c, 0x26, 0x98, 0x8b, 0x4c, 0x18, 0xce, 0x73, 0x20,
- 0x0c, 0xea, 0xb4, 0x1a, 0x81, 0xe0, 0x58, 0x4d, 0xf4, 0x5d, 0x0a, 0x4c, 0x1b, 0xf2, 0x63, 0x1a,
- 0x7f, 0xf4, 0xf9, 0x32, 0xa3, 0xb0, 0xeb, 0x25, 0x7f, 0x1b, 0xa7, 0xa0, 0xc5, 0xa9, 0xc4, 0xd0,
- 0x32, 0x4c, 0x8b, 0x17, 0xd1, 0xd1, 0x3d, 0xc0, 0x63, 0xbd, 0xb1, 0x35, 0x2d, 0xa7, 0xc0, 0x71,
- 0x6a, 0x2b, 0xf5, 0x23, 0x05, 0x18, 0x3b, 0x64, 0x12, 0xd3, 0xb6, 0x24, 0x73, 0xf4, 0xf0, 0x6e,
- 0x51, 0xa6, 0xda, 0x85, 0xd8, 0x81, 0x9e, 0x87, 0x89, 0x36, 0x9b, 0x08, 0x3f, 0x12, 0x9a, 0xf8,
- 0xa6, 0xbf, 0x85, 0xae, 0xdc, 0x7a, 0x04, 0x72, 0x6f, 0xaf, 0x38, 0x2b, 0xa3, 0x8f, 0x42, 0x71,
- 0x0c, 0x8f, 0xfa, 0xeb, 0x05, 0x40, 0x72, 0xf5, 0x25, 0x53, 0xdb, 0xb6, 0x1d, 0xf4, 0x79, 0x05,
- 0xc6, 0x74, 0x39, 0x6d, 0x14, 0x17, 0xb0, 0x9e, 0xef, 0x75, 0xb0, 0x1c, 0xfd, 0x9c, 0x9c, 0x0f,
- 0x8a, 0x0b, 0xc2, 0xfe, 0x73, 0xeb, 0x31, 0x19, 0x74, 0x2f, 0xf6, 0x1b, 0x47, 0xfa, 0x34, 0xfb,
- 0x31, 0x05, 0xa6, 0x12, 0x98, 0x52, 0x24, 0xe3, 0x17, 0xa2, 0x31, 0xd0, 0x8f, 0x24, 0x41, 0xa4,
- 0x2c, 0x5f, 0xff, 0xf8, 0x00, 0x9c, 0x4e, 0x59, 0x51, 0xe6, 0x62, 0x43, 0x62, 0xd2, 0x65, 0x2f,
- 0x2e, 0x36, 0x09, 0x49, 0x35, 0x70, 0xb1, 0x89, 0x43, 0x70, 0x82, 0x2e, 0x7a, 0x16, 0xfa, 0x74,
- 0xc7, 0x10, 0x9b, 0xf6, 0xd1, 0x5c, 0x53, 0x80, 0x2b, 0x0b, 0xa3, 0x82, 0x62, 0x5f, 0x09, 0x57,
- 0x30, 0x45, 0x48, 0xcf, 0x62, 0xf9, 0x18, 0xf1, 0x05, 0x56, 0x76, 0x16, 0xcb, 0xa7, 0x8d, 0x8b,
- 0xa3, 0xf5, 0xd0, 0xf3, 0x30, 0x23, 0x34, 0x55, 0x3f, 0x92, 0x89, 0x6d, 0xb9, 0x1e, 0xe5, 0xf8,
- 0x9e, 0x90, 0x29, 0x98, 0xf7, 0xeb, 0xcd, 0x8c, 0x3a, 0x38, 0xb3, 0x35, 0xfa, 0x4e, 0x98, 0x88,
- 0x70, 0x0f, 0x3f, 0x2a, 0x59, 0xce, 0x27, 0x33, 0x32, 0x26, 0xce, 0x2b, 0xa3, 0x65, 0x38, 0x46,
- 0x0d, 0xfd, 0xbf, 0x0a, 0x4c, 0x05, 0x1b, 0x75, 0x97, 0x6f, 0x79, 0x3f, 0x83, 0xdf, 0xd2, 0xd1,
- 0x7c, 0x41, 0x52, 0x7a, 0xd5, 0x38, 0x21, 0x9c, 0xa4, 0xad, 0xfe, 0xf0, 0x20, 0xc8, 0x19, 0x9d,
- 0xd1, 0x4a, 0x2f, 0x76, 0xc9, 0x70, 0x0f, 0xf8, 0xb6, 0xc9, 0x15, 0xe8, 0x6b, 0xb4, 0xda, 0x39,
- 0x0d, 0x93, 0x01, 0xba, 0xeb, 0x14, 0x5d, 0xa3, 0xd5, 0x46, 0xcf, 0x06, 0xa6, 0xce, 0x7c, 0xc6,
- 0xc8, 0xe0, 0xa9, 0x64, 0xcc, 0xdc, 0xe9, 0xb3, 0xf7, 0xfe, 0x4c, 0xf6, 0xde, 0x84, 0x21, 0x57,
- 0xd8, 0x41, 0x07, 0xf2, 0x87, 0x91, 0x94, 0x66, 0x5a, 0xd8, 0x3d, 0xb9, 0x85, 0xc6, 0x37, 0x8b,
- 0xfa, 0x34, 0xa8, 0x22, 0xd8, 0x66, 0xe7, 0x92, 0x08, 0x92, 0xc4, 0x14, 0xc1, 0x75, 0x56, 0x82,
- 0x05, 0x24, 0x21, 0xcc, 0x0d, 0x75, 0x23, 0xcc, 0xa1, 0xcf, 0xc5, 0xf9, 0xf7, 0x30, 0xdb, 0x7d,
- 0xcf, 0xf4, 0x38, 0x9c, 0xff, 0xcb, 0x18, 0xf7, 0xff, 0x13, 0x1e, 0x7e, 0xd2, 0x62, 0xa1, 0xfb,
- 0x60, 0x80, 0x45, 0x51, 0x12, 0x72, 0x40, 0x60, 0xdc, 0x60, 0x71, 0x74, 0x30, 0x87, 0xa1, 0x9a,
- 0x08, 0x1d, 0x98, 0x6f, 0xd3, 0x33, 0xdf, 0x46, 0x41, 0x4f, 0x8a, 0x33, 0x78, 0x25, 0xf2, 0x26,
- 0x32, 0x4d, 0x87, 0x58, 0x87, 0xa1, 0xa6, 0x61, 0x31, 0x77, 0x8f, 0x7c, 0x46, 0x74, 0xee, 0x82,
- 0xc5, 0x51, 0x60, 0x1f, 0x97, 0xfa, 0xe7, 0x05, 0xca, 0x20, 0x42, 0xa5, 0x7e, 0x97, 0x07, 0xc2,
- 0x15, 0xaf, 0xaf, 0x95, 0xfc, 0x46, 0x40, 0x09, 0xe9, 0x7c, 0x80, 0x90, 0x3b, 0x2a, 0x84, 0xbf,
- 0xb1, 0x44, 0x8c, 0x92, 0xf6, 0x8c, 0x26, 0x79, 0xce, 0xb0, 0xea, 0xf6, 0x1d, 0x31, 0xbd, 0xbd,
- 0x92, 0x5e, 0x0b, 0x10, 0x72, 0xd2, 0xe1, 0x6f, 0x2c, 0x11, 0xa3, 0x47, 0x12, 0x4b, 0xc6, 0x61,
- 0xb1, 0x4c, 0xbc, 0xa2, 0x6f, 0x3c, 0xcf, 0xb6, 0xf0, 0x3b, 0x66, 0x47, 0x52, 0x29, 0xa3, 0x0e,
- 0xce, 0x6c, 0xad, 0xfe, 0x8c, 0x02, 0x67, 0x52, 0xa7, 0x02, 0x5d, 0x87, 0xa9, 0xd0, 0x1d, 0x56,
- 0x16, 0x12, 0x86, 0x43, 0x1e, 0x7f, 0x33, 0x5e, 0x01, 0x27, 0xdb, 0xf0, 0xfc, 0x66, 0x09, 0x21,
- 0x44, 0xf8, 0xd2, 0xca, 0xaa, 0x96, 0x0c, 0xc6, 0x69, 0x6d, 0xd4, 0x17, 0x23, 0x9d, 0x0d, 0x27,
- 0x8b, 0x7e, 0x19, 0x1b, 0xa4, 0x11, 0xbc, 0x49, 0x0f, 0xbe, 0x8c, 0x05, 0x5a, 0x88, 0x39, 0x0c,
- 0x5d, 0x92, 0x43, 0x65, 0x04, 0xdc, 0xdd, 0x0f, 0x97, 0xa1, 0xfe, 0xaa, 0x02, 0xe7, 0x56, 0x34,
- 0xab, 0xad, 0x99, 0xfc, 0xf1, 0x7b, 0xd5, 0xb6, 0x4d, 0x31, 0x4d, 0x9d, 0xf2, 0xad, 0x2b, 0xaf,
- 0x97, 0x7c, 0xeb, 0xef, 0x87, 0x73, 0x19, 0xfe, 0x37, 0xa8, 0x0c, 0x63, 0xee, 0x1d, 0xad, 0xb5,
- 0x40, 0xb6, 0xb4, 0x6d, 0x43, 0x04, 0xd6, 0xe2, 0x6e, 0xda, 0x63, 0x35, 0xa9, 0xfc, 0x5e, 0xec,
- 0x37, 0x8e, 0xb4, 0x52, 0x3d, 0x00, 0xe1, 0xce, 0x6f, 0x58, 0x0d, 0xb4, 0x09, 0xc3, 0x9a, 0x49,
- 0x1c, 0x2f, 0x0c, 0x1e, 0xf9, 0xad, 0xb9, 0xec, 0xb4, 0x02, 0x07, 0x7f, 0xbe, 0xe6, 0xff, 0xc2,
- 0x01, 0x6e, 0xf5, 0x9f, 0x28, 0x70, 0x36, 0x3d, 0x94, 0x52, 0x17, 0x6a, 0x51, 0x13, 0x46, 0x9d,
- 0xb0, 0x99, 0xf8, 0x68, 0xdf, 0x25, 0x67, 0xa8, 0x90, 0x1e, 0xde, 0x50, 0x45, 0xb0, 0xe4, 0xd8,
- 0xae, 0xbf, 0x73, 0xe3, 0x49, 0x2b, 0x02, 0xab, 0x98, 0xd4, 0x13, 0x2c, 0xe3, 0x67, 0x09, 0x64,
- 0x28, 0x75, 0xb7, 0xa5, 0xe9, 0xa4, 0x7e, 0xc2, 0x39, 0xd5, 0x8f, 0x20, 0x6b, 0x43, 0x7a, 0xdf,
- 0x8f, 0x37, 0x81, 0x4c, 0x06, 0xcd, 0x83, 0x13, 0xc8, 0xa4, 0x37, 0x7c, 0x83, 0x64, 0x36, 0x48,
- 0xef, 0x7c, 0xc6, 0xc3, 0xf7, 0xff, 0x32, 0x98, 0x35, 0xda, 0x43, 0x26, 0x66, 0xdf, 0x3e, 0xc6,
- 0xc4, 0xec, 0x13, 0xdf, 0x48, 0xca, 0x9e, 0x92, 0x94, 0x3d, 0x96, 0x28, 0x7c, 0xf0, 0x84, 0x12,
- 0x85, 0xbf, 0x02, 0x83, 0x2d, 0xcd, 0x21, 0x96, 0x7f, 0x97, 0x5b, 0xc9, 0xe7, 0x68, 0x10, 0x6e,
- 0xb4, 0x90, 0x0b, 0x06, 0x9f, 0x64, 0x95, 0x11, 0xc0, 0x82, 0x50, 0x4a, 0xf0, 0x94, 0xe1, 0xe3,
- 0x8a, 0x4e, 0x18, 0xa6, 0x28, 0x1f, 0x39, 0x8e, 0x14, 0xe5, 0xea, 0xdf, 0x2a, 0x70, 0xb1, 0x13,
- 0x5b, 0x62, 0x06, 0x14, 0x3d, 0xf6, 0x19, 0xf6, 0x62, 0x40, 0x49, 0x70, 0xdb, 0xc0, 0x80, 0x12,
- 0x87, 0xe0, 0x04, 0x5d, 0xf4, 0x5e, 0x40, 0xf6, 0x06, 0xf7, 0xeb, 0xb9, 0x4e, 0x69, 0xf0, 0xd7,
- 0xb4, 0x05, 0xf6, 0x56, 0x21, 0xc8, 0x6b, 0x79, 0x2b, 0x51, 0x03, 0xa7, 0xb4, 0x52, 0x7f, 0xb9,
- 0x00, 0xb0, 0x4a, 0xbc, 0x3b, 0xb6, 0x73, 0x9b, 0x9e, 0xf1, 0x17, 0x23, 0x57, 0x07, 0xc3, 0x5f,
- 0xbf, 0x78, 0x94, 0x17, 0xa1, 0xbf, 0x65, 0xd7, 0x5d, 0xa1, 0x7f, 0xb0, 0x8e, 0xb0, 0xa7, 0x1a,
- 0xac, 0x14, 0x15, 0x61, 0x80, 0x39, 0x3d, 0x09, 0x05, 0x9a, 0x5d, 0x3c, 0xb0, 0xcb, 0x15, 0xcc,
- 0xcb, 0x29, 0x87, 0x14, 0x31, 0x0d, 0x5c, 0x71, 0xb9, 0x33, 0xc6, 0x63, 0x88, 0xf3, 0x32, 0x1c,
- 0x40, 0xd1, 0xe3, 0x00, 0x46, 0x6b, 0x49, 0x6b, 0x1a, 0xa6, 0x21, 0x3e, 0xd7, 0x11, 0x66, 0x11,
- 0x87, 0x4a, 0xd5, 0x2f, 0xbd, 0xb7, 0x57, 0x1c, 0x16, 0xbf, 0x76, 0xb1, 0x54, 0x5b, 0xfd, 0xa2,
- 0x02, 0x93, 0xe1, 0xe4, 0x89, 0xad, 0xe2, 0xf7, 0x9c, 0x07, 0x03, 0xce, 0xec, 0x39, 0x0f, 0xdb,
- 0xdf, 0xb9, 0xe7, 0xdc, 0x80, 0x95, 0xd5, 0xf3, 0x87, 0x60, 0x94, 0xf0, 0x90, 0x47, 0x95, 0x32,
- 0xe6, 0x3c, 0x6e, 0x84, 0xab, 0x73, 0x8b, 0x61, 0x31, 0x96, 0xeb, 0xa8, 0x7f, 0xdf, 0x07, 0x63,
- 0xab, 0x0d, 0xc3, 0xda, 0xf1, 0x63, 0x3b, 0x05, 0x17, 0xef, 0xca, 0xf1, 0x5c, 0xbc, 0x3f, 0x0f,
- 0x33, 0xa6, 0x7c, 0xcd, 0xc5, 0x05, 0x27, 0xcd, 0x6a, 0x04, 0x33, 0xc0, 0xf4, 0x98, 0xe5, 0x8c,
- 0x3a, 0x38, 0xb3, 0x35, 0xf2, 0x60, 0x50, 0xf7, 0xf3, 0x2b, 0xe6, 0x8e, 0x57, 0x24, 0xcf, 0xc5,
- 0x9c, 0x1c, 0xba, 0x23, 0xe0, 0x79, 0x62, 0x7b, 0x0a, 0x5a, 0xe8, 0xa3, 0x0a, 0x9c, 0x21, 0x3b,
- 0x3c, 0x74, 0xcd, 0x9a, 0xa3, 0x6d, 0x6e, 0x1a, 0xba, 0x78, 0xf1, 0xc7, 0x77, 0xe2, 0xf2, 0xfe,
- 0x5e, 0xf1, 0xcc, 0x62, 0x5a, 0x85, 0x7b, 0x7b, 0xc5, 0x6b, 0xa9, 0x91, 0x84, 0xd8, 0x6a, 0xa6,
- 0x36, 0xc1, 0xe9, 0xa4, 0x66, 0x1f, 0x83, 0xd1, 0x43, 0xbc, 0x13, 0x8f, 0xc4, 0x0b, 0xfa, 0x95,
- 0x02, 0x8c, 0xd1, 0xed, 0xb6, 0x6c, 0xeb, 0x9a, 0x59, 0x5e, 0xad, 0xa1, 0x07, 0xe2, 0x61, 0x12,
- 0x83, 0x2b, 0xc6, 0x44, 0xa8, 0xc4, 0x65, 0x98, 0xde, 0xb4, 0x1d, 0x9d, 0xac, 0x95, 0xaa, 0x6b,
- 0xb6, 0x70, 0x3e, 0x2b, 0xaf, 0xd6, 0x84, 0x5e, 0xc7, 0xae, 0x3c, 0x96, 0x52, 0xe0, 0x38, 0xb5,
- 0x15, 0xba, 0x05, 0x67, 0xc2, 0xf2, 0xf5, 0x16, 0x7f, 0xb0, 0x40, 0xd1, 0xf5, 0x85, 0x0f, 0x2e,
- 0x96, 0xd2, 0x2a, 0xe0, 0xf4, 0x76, 0x48, 0x83, 0x0b, 0xe2, 0x6e, 0x65, 0xc9, 0x76, 0xee, 0x68,
- 0x4e, 0x3d, 0x8a, 0xb6, 0x3f, 0xcc, 0x55, 0x5e, 0xce, 0xae, 0x86, 0x3b, 0xe1, 0x50, 0xff, 0x4e,
- 0x81, 0x68, 0x10, 0x4a, 0x74, 0x1e, 0xfa, 0x1c, 0x91, 0xbe, 0x4f, 0x04, 0x63, 0xa4, 0x2a, 0x02,
- 0x2d, 0x43, 0x73, 0x00, 0x4e, 0x18, 0x09, 0xb3, 0x10, 0xa6, 0xb5, 0x90, 0x62, 0x58, 0x4a, 0x35,
- 0x28, 0x2a, 0x4f, 0x6b, 0x08, 0x86, 0xc7, 0x50, 0xad, 0x69, 0x0d, 0x4c, 0xcb, 0x58, 0xfe, 0x12,
- 0xa3, 0x41, 0x5c, 0xdf, 0x1c, 0xcd, 0xf3, 0x97, 0xb0, 0x12, 0x2c, 0x20, 0x48, 0x83, 0xf1, 0x56,
- 0xdb, 0x14, 0xf1, 0x94, 0xa8, 0xea, 0xc3, 0xcd, 0x86, 0x57, 0xd3, 0x92, 0xf3, 0xb1, 0xd5, 0x4f,
- 0xcd, 0xd0, 0x57, 0x95, 0x51, 0xe0, 0x28, 0x46, 0xf5, 0xc7, 0x06, 0x41, 0x0a, 0xaf, 0x73, 0x08,
- 0x29, 0xf4, 0x27, 0x15, 0x98, 0xd6, 0x4d, 0x83, 0x58, 0x5e, 0x2c, 0x52, 0x05, 0x3f, 0x3e, 0xd6,
- 0x73, 0xc5, 0xfd, 0x69, 0x11, 0xab, 0x52, 0x16, 0xcf, 0x5b, 0x4a, 0x29, 0xc8, 0xc5, 0x13, 0xa0,
- 0x14, 0x08, 0x4e, 0xed, 0x0c, 0x1b, 0x0f, 0x2b, 0xaf, 0x94, 0xe5, 0xe8, 0x99, 0x25, 0x51, 0x86,
- 0x03, 0x28, 0xe5, 0xbc, 0x0d, 0xc7, 0x6e, 0xb7, 0xdc, 0x12, 0x7b, 0xc5, 0xca, 0x17, 0x85, 0x71,
+ 0xf7, 0xc8, 0xe0, 0x27, 0x0e, 0xd1, 0xa3, 0xf7, 0x02, 0xb2, 0x37, 0xd8, 0x4d, 0xbe, 0x7e, 0x9d,
+ 0x5f, 0x52, 0xe9, 0x60, 0xe9, 0xf2, 0xf7, 0x2d, 0xcc, 0x8a, 0x7d, 0x89, 0x6e, 0x25, 0x6a, 0xe0,
+ 0x94, 0x56, 0xe8, 0x36, 0xa0, 0xe0, 0xa2, 0xcb, 0x4f, 0xfb, 0x03, 0xb6, 0x46, 0x50, 0x49, 0x6c,
+ 0x8d, 0xb3, 0x94, 0xd8, 0xf5, 0x04, 0x0a, 0x9c, 0x82, 0x56, 0xfd, 0xad, 0x02, 0x8c, 0xf2, 0x2d,
+ 0xc2, 0x2f, 0x23, 0xc7, 0x7f, 0x56, 0x90, 0xc8, 0x59, 0x51, 0xca, 0xff, 0xf9, 0xb3, 0x0e, 0x67,
+ 0x1e, 0x15, 0xcd, 0xd8, 0x51, 0xb1, 0xd8, 0x2b, 0xa1, 0xce, 0x27, 0xc5, 0x1f, 0x2b, 0x70, 0x4a,
+ 0xaa, 0x7d, 0x02, 0x07, 0x45, 0x3d, 0x7a, 0x50, 0x3c, 0xd5, 0xe3, 0xf8, 0x32, 0xce, 0x09, 0x3b,
+ 0x32, 0x2c, 0xc6, 0xc3, 0x1f, 0x06, 0xd8, 0x60, 0xec, 0x44, 0x12, 0x6d, 0x83, 0x25, 0x5f, 0x08,
+ 0x20, 0x58, 0xaa, 0x15, 0x61, 0x8a, 0x85, 0x4e, 0x4c, 0x51, 0xfd, 0xf7, 0x7d, 0x30, 0x95, 0x98,
+ 0xf6, 0x24, 0x1f, 0x51, 0xbe, 0x41, 0x7c, 0xa4, 0xf0, 0x8d, 0xe0, 0x23, 0x7d, 0xb9, 0xf8, 0x48,
+ 0xf7, 0x07, 0x91, 0x03, 0xa8, 0x69, 0x34, 0x78, 0xb3, 0x9a, 0xa7, 0x39, 0xde, 0x9a, 0xd1, 0x24,
+ 0x82, 0xe3, 0x7c, 0x6b, 0x77, 0x5b, 0x96, 0xb6, 0xe0, 0x8c, 0x67, 0x25, 0x81, 0x09, 0xa7, 0x60,
+ 0x57, 0xbf, 0xa7, 0x00, 0x43, 0x0b, 0x9a, 0xcb, 0x7a, 0xfa, 0x41, 0x18, 0x13, 0xa8, 0x2b, 0x4d,
+ 0xad, 0x41, 0x7a, 0x51, 0x47, 0x08, 0x94, 0x2b, 0x12, 0x3a, 0x7e, 0xa3, 0x93, 0x4b, 0x70, 0x84,
+ 0x1c, 0xda, 0x85, 0xd1, 0x66, 0x78, 0x7b, 0x11, 0x4b, 0xbc, 0xd4, 0x3b, 0x75, 0x8a, 0x8d, 0x5f,
+ 0x5b, 0xa5, 0x02, 0x2c, 0xd3, 0x52, 0x5f, 0x82, 0xd3, 0x29, 0x3d, 0xee, 0xe2, 0xe2, 0xf6, 0x16,
+ 0x18, 0xa2, 0x77, 0xef, 0x50, 0x0c, 0x1b, 0xdd, 0xdf, 0x2b, 0x0e, 0x3d, 0xcb, 0x8b, 0xb0, 0x0f,
+ 0x53, 0xdf, 0x45, 0x05, 0x80, 0x78, 0x9f, 0xba, 0x51, 0xf0, 0x0d, 0x00, 0x94, 0xe6, 0xb1, 0xed,
+ 0xf1, 0xad, 0xf4, 0x14, 0x0c, 0xb4, 0xb6, 0x34, 0xd7, 0x6f, 0xf1, 0x80, 0xcf, 0x2a, 0xaa, 0xb4,
+ 0xf0, 0xde, 0x5e, 0x71, 0x46, 0x16, 0x44, 0x44, 0x23, 0x06, 0xc3, 0xbc, 0x1d, 0xdd, 0x61, 0x74,
+ 0x93, 0x97, 0xec, 0x66, 0xcb, 0x24, 0x14, 0xca, 0x76, 0x58, 0x21, 0xdf, 0x0e, 0x5b, 0x4e, 0x60,
+ 0xc2, 0x29, 0xd8, 0x7d, 0x9a, 0x15, 0xcb, 0xf0, 0x0c, 0x2d, 0xa0, 0xd9, 0x97, 0x9f, 0x66, 0x14,
+ 0x13, 0x4e, 0xc1, 0x8e, 0x3e, 0xa9, 0xc0, 0x6c, 0xb4, 0x78, 0xc9, 0xb0, 0x0c, 0x77, 0x8b, 0xd4,
+ 0x19, 0xf1, 0xfe, 0x43, 0x13, 0xbf, 0xbc, 0xbf, 0x57, 0x9c, 0x5d, 0xce, 0xc4, 0x88, 0x3b, 0x50,
+ 0x43, 0x3f, 0xa0, 0xc0, 0x85, 0xd8, 0xbc, 0x38, 0x46, 0xa3, 0x41, 0x1c, 0xd1, 0x9b, 0xc3, 0x7f,
+ 0xe0, 0xc5, 0xfd, 0xbd, 0xe2, 0x85, 0xe5, 0x6c, 0x94, 0xb8, 0x13, 0x3d, 0xf4, 0x53, 0x0a, 0x9c,
+ 0x6d, 0x11, 0xab, 0x6e, 0x58, 0x8d, 0xe7, 0x6c, 0xe7, 0x36, 0x71, 0x5c, 0x6c, 0x9b, 0xa6, 0xdd,
+ 0xf6, 0xdc, 0x99, 0x41, 0x76, 0x86, 0x55, 0xf2, 0x7c, 0x73, 0xd5, 0x34, 0x8c, 0x0b, 0x97, 0xc5,
+ 0x16, 0x3d, 0x9b, 0x0a, 0x76, 0x71, 0x46, 0x47, 0xd4, 0xdf, 0x54, 0xa0, 0xaf, 0x84, 0x2b, 0xe8,
+ 0xc1, 0xc8, 0x27, 0x72, 0x4e, 0xfe, 0x44, 0xee, 0xed, 0x15, 0x87, 0x4a, 0xb8, 0x22, 0x7d, 0x8c,
+ 0x3f, 0xa0, 0xc0, 0x94, 0x6e, 0x5b, 0x9e, 0x46, 0xe7, 0x0e, 0x73, 0x59, 0xd9, 0x3f, 0x97, 0x73,
+ 0x5d, 0x86, 0x4b, 0x31, 0x64, 0xa1, 0xb2, 0x3b, 0x0e, 0x71, 0x71, 0x92, 0xb2, 0xfa, 0x79, 0x05,
+ 0xa6, 0x4b, 0x5a, 0x4b, 0xa8, 0x82, 0xca, 0x64, 0xd3, 0xa0, 0x1b, 0xa4, 0x1b, 0xcd, 0x3e, 0xda,
+ 0x82, 0x41, 0xa6, 0x6d, 0x76, 0x7b, 0xb9, 0xcb, 0x87, 0xb4, 0x9f, 0x65, 0xb8, 0xb8, 0x1e, 0x84,
+ 0xff, 0x8f, 0x05, 0x7e, 0xf5, 0x09, 0x98, 0x8c, 0xd7, 0x43, 0x45, 0x5f, 0xa6, 0xe1, 0xca, 0xc7,
+ 0x91, 0xb8, 0x38, 0xf2, 0xf8, 0xf0, 0xff, 0xfb, 0x5a, 0xf1, 0x4d, 0x1f, 0xfe, 0xb3, 0x2b, 0x6f,
+ 0x52, 0xbf, 0xaa, 0xc0, 0x58, 0xc9, 0xb4, 0xdb, 0xf5, 0xaa, 0x63, 0x6f, 0x1a, 0x26, 0x79, 0x63,
+ 0x68, 0x39, 0xe4, 0x1e, 0x67, 0x89, 0xae, 0x4c, 0xeb, 0x20, 0x57, 0x7c, 0x83, 0x68, 0x1d, 0xe4,
+ 0x2e, 0x67, 0x48, 0x93, 0x2f, 0xc2, 0x19, 0xb9, 0x56, 0xa8, 0x32, 0xbd, 0x02, 0xfd, 0xb7, 0x0d,
+ 0xab, 0x1e, 0xdf, 0x98, 0x37, 0x0d, 0xab, 0x8e, 0x19, 0x24, 0xd8, 0xba, 0x85, 0xcc, 0x33, 0xeb,
+ 0x6f, 0x46, 0xa2, 0xd3, 0xc6, 0x84, 0xd5, 0xab, 0x30, 0xac, 0x6b, 0x0b, 0x6d, 0xab, 0x6e, 0x06,
+ 0xbb, 0x9e, 0x4e, 0x41, 0x69, 0x9e, 0x97, 0xe1, 0x00, 0x8a, 0xee, 0x02, 0x84, 0xaf, 0x13, 0xbd,
+ 0x08, 0x01, 0xe1, 0xc3, 0x47, 0x8d, 0x78, 0x9e, 0x61, 0x35, 0xdc, 0x70, 0x5f, 0x85, 0x30, 0x2c,
+ 0x51, 0x43, 0x1f, 0x84, 0x71, 0x59, 0x22, 0xe1, 0x6a, 0xd2, 0x9c, 0xcb, 0x10, 0x11, 0x7d, 0xce,
+ 0x08, 0xc2, 0xe3, 0x72, 0xa9, 0x8b, 0xa3, 0xd4, 0xd0, 0x6e, 0x20, 0x7f, 0x71, 0x25, 0x6d, 0x7f,
+ 0xfe, 0x1b, 0x85, 0x2c, 0xfa, 0x4c, 0x0b, 0xe2, 0x63, 0x11, 0xa5, 0x71, 0x84, 0x54, 0x8a, 0x62,
+ 0x66, 0xe0, 0xb8, 0x14, 0x33, 0x04, 0x86, 0xb8, 0x6a, 0xca, 0x3f, 0x6e, 0x1e, 0xcf, 0x33, 0x40,
+ 0xae, 0xe5, 0x0a, 0x9f, 0xdb, 0xf8, 0x6f, 0x17, 0xfb, 0xb8, 0xd1, 0x36, 0x8c, 0x51, 0xc1, 0xba,
+ 0x46, 0x4c, 0xa2, 0x7b, 0xb6, 0x33, 0x33, 0x94, 0xff, 0x39, 0xab, 0x26, 0xe1, 0xe1, 0x52, 0xac,
+ 0x5c, 0x82, 0x23, 0x74, 0x02, 0xcd, 0xdd, 0x70, 0xa6, 0xe6, 0xae, 0x0d, 0xa3, 0xdb, 0x92, 0x2a,
+ 0x7e, 0x84, 0x4d, 0xc2, 0x93, 0x79, 0x3a, 0x16, 0xea, 0xe5, 0x17, 0x4e, 0x0b, 0x42, 0xa3, 0xb2,
+ 0x0e, 0x5f, 0xa6, 0x83, 0x36, 0x60, 0x68, 0x83, 0xcb, 0xa0, 0x33, 0xc0, 0xe6, 0xe2, 0x3d, 0x3d,
+ 0x88, 0xd6, 0x5c, 0xce, 0x15, 0x3f, 0xb0, 0x8f, 0x18, 0xbd, 0x04, 0x83, 0xa6, 0xd1, 0x34, 0x3c,
+ 0x77, 0x66, 0x94, 0x91, 0xc8, 0xb5, 0xb4, 0xcb, 0x0c, 0x03, 0x3f, 0xac, 0xf8, 0xff, 0x58, 0x60,
+ 0x45, 0x9f, 0x56, 0xe0, 0xb4, 0xd8, 0x86, 0xc1, 0xa1, 0x65, 0x10, 0x77, 0x66, 0x8c, 0xcd, 0xe1,
+ 0x8d, 0xde, 0x0e, 0xc9, 0xf0, 0x80, 0x5e, 0xb8, 0x20, 0x66, 0xf3, 0xf4, 0x4a, 0x92, 0x18, 0x4e,
+ 0xeb, 0x81, 0xfa, 0x2f, 0xc6, 0x61, 0xaa, 0x64, 0xb6, 0x5d, 0x8f, 0x38, 0xf3, 0xc2, 0x92, 0x85,
+ 0x38, 0xe8, 0xa3, 0x0a, 0x9c, 0x65, 0xff, 0x96, 0xed, 0x3b, 0x56, 0x99, 0x98, 0xda, 0xee, 0xfc,
+ 0x26, 0xad, 0x51, 0xaf, 0x1f, 0xee, 0xf0, 0x28, 0xb7, 0xc5, 0x35, 0x99, 0xbd, 0xd8, 0xd4, 0x52,
+ 0x31, 0xe2, 0x0c, 0x4a, 0xe8, 0xfb, 0x15, 0x38, 0x9f, 0x02, 0x2a, 0x13, 0x93, 0x78, 0xbe, 0xf0,
+ 0x7f, 0xd8, 0x7e, 0x5c, 0xda, 0xdf, 0x2b, 0x9e, 0xaf, 0x65, 0x21, 0xc5, 0xd9, 0xf4, 0xd0, 0x0f,
+ 0x2a, 0x30, 0x9b, 0x02, 0x5d, 0xd2, 0x0c, 0xb3, 0xed, 0xf8, 0xf7, 0x82, 0xc3, 0x76, 0x87, 0x89,
+ 0xe7, 0xb5, 0x4c, 0xac, 0xb8, 0x03, 0x45, 0xf4, 0x21, 0x38, 0x13, 0x40, 0xd7, 0x2d, 0x8b, 0x90,
+ 0x7a, 0xe4, 0x96, 0x70, 0xd8, 0xae, 0x9c, 0xdf, 0xdf, 0x2b, 0x9e, 0xa9, 0xa5, 0x21, 0xc4, 0xe9,
+ 0x74, 0x50, 0x03, 0x2e, 0x85, 0x00, 0xcf, 0x30, 0x8d, 0xbb, 0xfc, 0x22, 0xb3, 0xe5, 0x10, 0x77,
+ 0xcb, 0x36, 0xeb, 0x8c, 0x15, 0x2b, 0x0b, 0x6f, 0xde, 0xdf, 0x2b, 0x5e, 0xaa, 0x75, 0xaa, 0x88,
+ 0x3b, 0xe3, 0x41, 0x75, 0x18, 0x73, 0x75, 0xcd, 0xaa, 0x58, 0x1e, 0x71, 0xb6, 0x35, 0x73, 0x66,
+ 0x30, 0xd7, 0x00, 0x39, 0x03, 0x94, 0xf0, 0xe0, 0x08, 0x56, 0xf4, 0x6e, 0x18, 0x26, 0x3b, 0x2d,
+ 0xcd, 0xaa, 0x13, 0xce, 0x74, 0x47, 0x16, 0x2e, 0xd2, 0xa3, 0x7e, 0x51, 0x94, 0xdd, 0xdb, 0x2b,
+ 0x8e, 0xf9, 0xff, 0xaf, 0xd8, 0x75, 0x82, 0x83, 0xda, 0xe8, 0x03, 0x30, 0xcd, 0x4c, 0x6d, 0xea,
+ 0x84, 0x1d, 0x21, 0xae, 0x7f, 0x57, 0x1c, 0xce, 0xd5, 0x4f, 0xf6, 0x0c, 0xbf, 0x92, 0x82, 0x0f,
+ 0xa7, 0x52, 0xa1, 0xcb, 0xd0, 0xd4, 0x76, 0xae, 0x3b, 0x9a, 0x4e, 0x36, 0xdb, 0xe6, 0x1a, 0x71,
+ 0x9a, 0x86, 0xc5, 0x95, 0x25, 0x44, 0xb7, 0xad, 0x3a, 0x65, 0xd4, 0xca, 0xd5, 0x01, 0xbe, 0x0c,
+ 0x2b, 0x9d, 0x2a, 0xe2, 0xce, 0x78, 0xd0, 0x23, 0x30, 0x66, 0x34, 0x2c, 0xdb, 0x21, 0x6b, 0x9a,
+ 0x61, 0x79, 0xee, 0x0c, 0x30, 0x21, 0x9b, 0x4d, 0x6b, 0x45, 0x2a, 0xc7, 0x91, 0x5a, 0x68, 0x1b,
+ 0x90, 0x45, 0xee, 0x54, 0xed, 0x3a, 0xdb, 0x02, 0xeb, 0x2d, 0xb6, 0x91, 0x05, 0x9b, 0x3d, 0xec,
+ 0xd4, 0xb0, 0xab, 0xf4, 0x6a, 0x02, 0x1b, 0x4e, 0xa1, 0x80, 0x96, 0x00, 0x35, 0xb5, 0x9d, 0xc5,
+ 0x66, 0xcb, 0xdb, 0x5d, 0x68, 0x9b, 0xb7, 0x05, 0xd7, 0x18, 0x63, 0x73, 0xc1, 0x15, 0x4d, 0x09,
+ 0x28, 0x4e, 0x69, 0x81, 0x34, 0xb8, 0xc0, 0xc7, 0x53, 0xd6, 0x48, 0xd3, 0xb6, 0x5c, 0xe2, 0xb9,
+ 0xd2, 0x26, 0x9d, 0x19, 0x67, 0x06, 0x17, 0xec, 0x62, 0x5b, 0xc9, 0xae, 0x86, 0x3b, 0xe1, 0x88,
+ 0x9a, 0x9c, 0x4d, 0x1c, 0x60, 0x72, 0xf6, 0x28, 0x8c, 0xbb, 0x9e, 0xe6, 0x78, 0xed, 0x96, 0x58,
+ 0x86, 0x53, 0x6c, 0x19, 0x98, 0x1e, 0xb2, 0x26, 0x03, 0x70, 0xb4, 0x1e, 0x5d, 0x3e, 0xae, 0x6c,
+ 0x16, 0xed, 0x26, 0xc3, 0xe5, 0xab, 0x49, 0xe5, 0x38, 0x52, 0x0b, 0xad, 0xc3, 0xb9, 0xa6, 0xb6,
+ 0x13, 0x7c, 0xbe, 0x55, 0xcd, 0xd1, 0x4c, 0x93, 0x98, 0x86, 0xdb, 0x9c, 0x99, 0x62, 0x3d, 0x65,
+ 0x2f, 0xfc, 0x2b, 0xe9, 0x55, 0x70, 0x56, 0x5b, 0x61, 0x83, 0x56, 0x76, 0x34, 0x23, 0x82, 0x12,
+ 0x45, 0x6c, 0xd0, 0xe2, 0x60, 0x9c, 0xd6, 0x46, 0xfd, 0xef, 0xfd, 0x30, 0x93, 0x38, 0xc1, 0x7c,
+ 0x43, 0xb2, 0x03, 0x79, 0x94, 0x72, 0x44, 0x3c, 0xaa, 0x05, 0x57, 0x82, 0x0a, 0xd7, 0x5b, 0xed,
+ 0x54, 0x5a, 0x05, 0x46, 0xeb, 0xfe, 0xfd, 0xbd, 0xe2, 0x95, 0xda, 0x01, 0x75, 0xf1, 0x81, 0xd8,
+ 0xb2, 0xf9, 0x7f, 0xdf, 0x09, 0xf1, 0xff, 0x0f, 0xc0, 0xb4, 0x04, 0x70, 0x88, 0x56, 0xdf, 0xed,
+ 0xe1, 0xfc, 0x61, 0x6c, 0xaf, 0x96, 0x82, 0x0f, 0xa7, 0x52, 0xc9, 0x64, 0xba, 0x03, 0x27, 0xc1,
+ 0x74, 0xd5, 0xbd, 0x3e, 0x18, 0x29, 0xd9, 0x56, 0x9d, 0xeb, 0x45, 0x1e, 0x8a, 0xbc, 0x7a, 0x5f,
+ 0x92, 0x65, 0xe7, 0x7b, 0x7b, 0xc5, 0xf1, 0xa0, 0xa2, 0x24, 0x4c, 0x3f, 0x16, 0xbc, 0x2f, 0xf1,
+ 0x1b, 0xe9, 0x9b, 0xa3, 0x0f, 0x43, 0xf7, 0xf6, 0x8a, 0xa7, 0x82, 0x66, 0xd1, 0xb7, 0x22, 0xca,
+ 0x51, 0x4d, 0xcd, 0xf5, 0xd6, 0x1c, 0xcd, 0x72, 0x8d, 0x1e, 0x14, 0x93, 0xc1, 0x83, 0xc0, 0x72,
+ 0x02, 0x1b, 0x4e, 0xa1, 0x80, 0x5e, 0x86, 0x09, 0x5a, 0xba, 0xde, 0xaa, 0x6b, 0x1e, 0xc9, 0xa9,
+ 0x8f, 0x0c, 0x6c, 0x98, 0x96, 0x23, 0x98, 0x70, 0x0c, 0x33, 0xb7, 0x12, 0xd0, 0x5c, 0xdb, 0x62,
+ 0xeb, 0x19, 0xb1, 0x12, 0xa0, 0xa5, 0x58, 0x40, 0xd1, 0x03, 0x30, 0xd4, 0x24, 0xae, 0xab, 0x35,
+ 0x08, 0x93, 0x0a, 0x46, 0xc2, 0x8b, 0xd5, 0x0a, 0x2f, 0xc6, 0x3e, 0x1c, 0xbd, 0x0d, 0x06, 0x74,
+ 0xbb, 0x4e, 0xdc, 0x99, 0x21, 0xc6, 0xf8, 0xe8, 0x19, 0x30, 0x50, 0xa2, 0x05, 0xf7, 0xf6, 0x8a,
+ 0x23, 0xec, 0xf9, 0x84, 0xfe, 0xc2, 0xbc, 0x92, 0xfa, 0x93, 0x0a, 0x4c, 0xc6, 0x95, 0x65, 0x5d,
+ 0x58, 0x37, 0x9c, 0x9c, 0xa1, 0x80, 0xfa, 0x69, 0x05, 0xc6, 0x68, 0x0f, 0x1d, 0xdb, 0xac, 0x9a,
+ 0x9a, 0x45, 0xd0, 0xf7, 0x29, 0x30, 0xb9, 0x65, 0x34, 0xb6, 0x64, 0x3b, 0x2e, 0x21, 0xae, 0xe7,
+ 0x52, 0x36, 0xdd, 0x88, 0xe1, 0x5a, 0x98, 0xde, 0xdf, 0x2b, 0x4e, 0xc6, 0x4b, 0x71, 0x82, 0xa6,
+ 0xfa, 0x97, 0x05, 0x38, 0x27, 0xf7, 0x6c, 0x3e, 0x34, 0x91, 0x47, 0x7f, 0xac, 0x00, 0x34, 0x0d,
+ 0x6b, 0xde, 0x34, 0xed, 0x3b, 0xcc, 0xf8, 0x94, 0x5e, 0x80, 0x5e, 0xcc, 0xab, 0xe4, 0x4c, 0xa1,
+ 0x30, 0xb7, 0x12, 0x60, 0xe7, 0x0f, 0x93, 0xcf, 0xfb, 0xca, 0x93, 0x10, 0x70, 0x6f, 0xaf, 0x58,
+ 0x4c, 0xda, 0xe5, 0xcf, 0x61, 0x61, 0xfc, 0xbe, 0x6c, 0xb8, 0xde, 0x47, 0xff, 0xa2, 0x63, 0x15,
+ 0xfe, 0x42, 0x19, 0x0e, 0x64, 0xb6, 0x09, 0xa7, 0x62, 0x84, 0x53, 0x0c, 0x73, 0xcb, 0xb2, 0x61,
+ 0xee, 0x01, 0x4c, 0x6a, 0xce, 0x37, 0xc5, 0x9f, 0x7b, 0xa6, 0xad, 0x59, 0x1e, 0x9d, 0x69, 0xc9,
+ 0x90, 0xf7, 0xcf, 0x0b, 0x30, 0x2d, 0x26, 0xc0, 0xa4, 0x57, 0x94, 0x96, 0x69, 0xef, 0x36, 0x89,
+ 0x75, 0x12, 0xc6, 0x5a, 0xfe, 0x47, 0x50, 0xc8, 0xfc, 0x08, 0x9a, 0x89, 0x8f, 0xa0, 0x2f, 0xcf,
+ 0x47, 0x10, 0xf0, 0x8a, 0x03, 0x14, 0x33, 0x18, 0xce, 0x1a, 0x16, 0xed, 0xe8, 0x75, 0xb6, 0x61,
+ 0x42, 0x93, 0x4a, 0xc6, 0x9f, 0x86, 0xf9, 0xdd, 0xb3, 0x92, 0x5a, 0x03, 0x67, 0xb4, 0x54, 0xff,
+ 0x5a, 0x81, 0x99, 0xb4, 0xf9, 0x3d, 0x01, 0x5d, 0x6a, 0x33, 0xaa, 0x4b, 0xbd, 0xd1, 0xc3, 0xb7,
+ 0x11, 0xe9, 0x7a, 0x86, 0x4e, 0xf5, 0xaf, 0x0a, 0x70, 0x36, 0xac, 0x5e, 0xb1, 0x5c, 0x4f, 0x33,
+ 0x4d, 0x2e, 0x97, 0x1e, 0xff, 0x5e, 0x6a, 0x45, 0x54, 0xe2, 0xab, 0xbd, 0x0d, 0x55, 0xee, 0x7b,
+ 0xa6, 0x5d, 0xc7, 0x4e, 0xcc, 0xae, 0xa3, 0x7a, 0x84, 0x34, 0x3b, 0x9b, 0x78, 0xfc, 0x47, 0x05,
+ 0x66, 0xd3, 0x1b, 0x9e, 0xc0, 0xa6, 0xb2, 0xa3, 0x9b, 0xea, 0xbd, 0x47, 0x37, 0xea, 0x8c, 0x6d,
+ 0xf5, 0x0b, 0x85, 0xac, 0xd1, 0x32, 0xbd, 0xfa, 0x26, 0x9c, 0x72, 0x48, 0xc3, 0x70, 0x3d, 0x61,
+ 0x80, 0x70, 0x38, 0x1b, 0x6b, 0xff, 0x3d, 0xed, 0x14, 0x8e, 0xe2, 0xc0, 0x71, 0xa4, 0x68, 0x15,
+ 0x86, 0x5c, 0x42, 0xea, 0x14, 0x7f, 0xa1, 0x7b, 0xfc, 0x81, 0x10, 0x51, 0xe3, 0x6d, 0xb1, 0x8f,
+ 0x04, 0x7d, 0x07, 0x8c, 0xd7, 0x83, 0x2f, 0x8a, 0x62, 0xed, 0xeb, 0x1e, 0x2b, 0xbb, 0xa2, 0x95,
+ 0xe5, 0xd6, 0x38, 0x8a, 0x4c, 0xfd, 0x3b, 0x05, 0x2e, 0x76, 0xda, 0x5b, 0xe8, 0x15, 0x00, 0xdd,
+ 0x97, 0x0a, 0x5d, 0x71, 0x78, 0x3e, 0x91, 0x73, 0x2d, 0x39, 0x96, 0xf0, 0x03, 0x0d, 0x8a, 0x5c,
+ 0x2c, 0x11, 0x49, 0xb1, 0xf6, 0x2b, 0x1c, 0x93, 0xb5, 0x9f, 0xfa, 0x9f, 0x14, 0x99, 0x15, 0xc9,
+ 0x6b, 0xfb, 0x46, 0x63, 0x45, 0x72, 0xdf, 0x33, 0xdf, 0xe9, 0xbe, 0x52, 0x80, 0x2b, 0xe9, 0x4d,
+ 0xa4, 0xf3, 0xfc, 0x69, 0x18, 0x6c, 0x71, 0x3f, 0x08, 0x6e, 0x12, 0x7e, 0x95, 0x72, 0x16, 0xee,
+ 0xa5, 0x70, 0x6f, 0xaf, 0x38, 0x9b, 0xc6, 0xe8, 0x85, 0x7f, 0x83, 0x68, 0x87, 0x8c, 0xd8, 0x83,
+ 0x02, 0x17, 0xda, 0xdf, 0xd1, 0x25, 0x73, 0xd1, 0x36, 0x88, 0xd9, 0xf5, 0x1b, 0xc2, 0x47, 0x14,
+ 0x98, 0x88, 0xec, 0x68, 0x77, 0x66, 0x80, 0xed, 0xd1, 0x5c, 0x86, 0x56, 0x91, 0x4f, 0x25, 0x94,
+ 0x06, 0x22, 0xc5, 0x2e, 0x8e, 0x11, 0x8c, 0xb1, 0x59, 0x79, 0x56, 0xdf, 0x70, 0x6c, 0x56, 0xee,
+ 0x7c, 0x06, 0x9b, 0xfd, 0x89, 0x42, 0xd6, 0x68, 0x19, 0x9b, 0xbd, 0x03, 0x23, 0xbe, 0x18, 0xe9,
+ 0xb3, 0x8b, 0xa5, 0x5e, 0xfb, 0xc4, 0xd1, 0x2d, 0x4c, 0x89, 0xfe, 0x8c, 0xf8, 0x25, 0x2e, 0x0e,
+ 0x69, 0xa1, 0xef, 0x55, 0x00, 0xc2, 0x85, 0x11, 0x1f, 0xd5, 0xda, 0xd1, 0x4d, 0x87, 0x24, 0xd6,
+ 0x4c, 0xd0, 0x4f, 0x5a, 0xda, 0x14, 0x12, 0x5d, 0xf5, 0x5f, 0xf7, 0x03, 0x4a, 0xf6, 0xbd, 0xbb,
+ 0xe7, 0xe2, 0x03, 0x84, 0xdc, 0x16, 0x4c, 0x3a, 0x54, 0x5a, 0xd4, 0x0d, 0x93, 0x5d, 0x59, 0xed,
+ 0xb6, 0x97, 0x53, 0xf3, 0xc1, 0xae, 0x55, 0x38, 0x86, 0x0b, 0x27, 0xb0, 0xa3, 0xb7, 0xc0, 0x50,
+ 0xcb, 0x31, 0x9a, 0x9a, 0xb3, 0xcb, 0x2e, 0xc5, 0xc3, 0xfc, 0x2d, 0xab, 0xca, 0x8b, 0xb0, 0x0f,
+ 0x43, 0x1f, 0x80, 0x11, 0xd3, 0xd8, 0x24, 0xfa, 0xae, 0x6e, 0x12, 0xa1, 0x2a, 0xbf, 0x75, 0x34,
+ 0x6b, 0xbe, 0xec, 0xa3, 0x15, 0x16, 0x88, 0xfe, 0x4f, 0x1c, 0x12, 0x44, 0x15, 0x38, 0x7d, 0x87,
+ 0xd9, 0xc4, 0x98, 0xc4, 0x75, 0x6b, 0xed, 0x56, 0xcb, 0x76, 0x3c, 0x52, 0x67, 0x0a, 0xf5, 0x61,
+ 0xae, 0xd8, 0x7b, 0x2e, 0x09, 0xc6, 0x69, 0x6d, 0xd0, 0x13, 0x00, 0x5a, 0xdb, 0xb3, 0xb9, 0x43,
+ 0xe2, 0xcc, 0x30, 0xbb, 0xb5, 0x5f, 0xa2, 0x8b, 0x3d, 0x1f, 0x94, 0xde, 0xdb, 0x2b, 0x8e, 0x0a,
+ 0xdd, 0x1f, 0x5b, 0x1a, 0xa9, 0x01, 0x7a, 0x11, 0xa6, 0x75, 0x0e, 0x2a, 0xd9, 0xcd, 0x96, 0xe6,
+ 0x19, 0xe2, 0x46, 0x3c, 0xc2, 0x10, 0x7d, 0xcb, 0xfe, 0x5e, 0x71, 0xba, 0x94, 0x02, 0x8f, 0xa3,
+ 0x4c, 0x45, 0xa2, 0x7e, 0xb2, 0x00, 0x17, 0x3a, 0x4c, 0x10, 0xc2, 0xf4, 0xc3, 0x13, 0xeb, 0x27,
+ 0xb6, 0xd9, 0x23, 0xfc, 0x63, 0x11, 0x85, 0xf7, 0xf6, 0x8a, 0xf7, 0x75, 0x40, 0x50, 0xa3, 0xfb,
+ 0x9c, 0x34, 0x76, 0x71, 0x88, 0x06, 0x55, 0x60, 0xb0, 0x1e, 0xbe, 0x7d, 0x8d, 0x2c, 0x3c, 0x44,
+ 0x8f, 0x02, 0xae, 0xa5, 0xee, 0x16, 0x9b, 0x40, 0x80, 0x96, 0x61, 0x88, 0xdb, 0x54, 0x12, 0x71,
+ 0xac, 0x3c, 0xcc, 0x54, 0x26, 0xbc, 0xa8, 0x5b, 0x64, 0x3e, 0x0a, 0xf5, 0x6f, 0x15, 0x18, 0x2a,
+ 0xd9, 0x0e, 0x29, 0xaf, 0xd6, 0xd0, 0x2e, 0x8c, 0x4a, 0x1e, 0xf1, 0x82, 0xc5, 0xe6, 0xe4, 0x39,
+ 0x0c, 0xa3, 0x74, 0xb5, 0xf7, 0x7d, 0xf8, 0x82, 0x02, 0x2c, 0xd3, 0x42, 0xaf, 0xd0, 0x39, 0xbf,
+ 0xe3, 0x18, 0x1e, 0x25, 0xdc, 0x8b, 0x91, 0x0d, 0x27, 0x8c, 0x7d, 0x5c, 0x7c, 0xb7, 0x07, 0x3f,
+ 0x71, 0x48, 0x45, 0xad, 0x52, 0xf6, 0x12, 0xef, 0x26, 0x7a, 0x1c, 0xfa, 0x9b, 0x76, 0xdd, 0x5f,
+ 0xf7, 0xb7, 0xfa, 0xcc, 0x63, 0xc5, 0xae, 0xd3, 0xb9, 0x3d, 0x9b, 0x6c, 0xc1, 0xde, 0x93, 0x58,
+ 0x1b, 0x75, 0x15, 0x26, 0xe3, 0xf4, 0xd1, 0xe3, 0x30, 0xa1, 0xdb, 0xcd, 0xa6, 0x6d, 0xd5, 0xda,
+ 0x9b, 0x9b, 0xc6, 0x0e, 0x89, 0x38, 0x57, 0x96, 0x22, 0x10, 0x1c, 0xab, 0xa9, 0x7e, 0x4e, 0x81,
+ 0x3e, 0xba, 0x2e, 0x2a, 0x0c, 0xd6, 0xed, 0xa6, 0x66, 0x58, 0xa2, 0x57, 0xec, 0x95, 0xba, 0xcc,
+ 0x4a, 0xb0, 0x80, 0xa0, 0x16, 0x8c, 0xf8, 0x12, 0x59, 0x4f, 0x66, 0xe1, 0xe5, 0xd5, 0x5a, 0xe0,
+ 0x55, 0x13, 0x1c, 0x13, 0x7e, 0x89, 0x8b, 0x43, 0x22, 0xaa, 0x06, 0x53, 0xe5, 0xd5, 0x5a, 0xc5,
+ 0xd2, 0xcd, 0x76, 0x9d, 0x2c, 0xee, 0xb0, 0x3f, 0x94, 0xcf, 0x19, 0xbc, 0x44, 0x8c, 0x93, 0xf1,
+ 0x39, 0x51, 0x09, 0xfb, 0x30, 0x5a, 0x8d, 0xf0, 0x16, 0xc2, 0xd7, 0x90, 0x55, 0x13, 0x48, 0xb0,
+ 0x0f, 0x53, 0xbf, 0x5a, 0x80, 0x51, 0xa9, 0x43, 0xc8, 0x84, 0x21, 0x3e, 0x5c, 0xb7, 0x17, 0x7f,
+ 0xf2, 0x44, 0xaf, 0x39, 0x75, 0x3e, 0xa1, 0x2e, 0xf6, 0x49, 0xc8, 0x3c, 0xbb, 0xd0, 0x81, 0x67,
+ 0xcf, 0x45, 0x5c, 0x36, 0xf9, 0x27, 0x39, 0x91, 0xed, 0xae, 0x89, 0x2e, 0x8a, 0xe3, 0x89, 0xdb,
+ 0x65, 0x0f, 0xc7, 0x8e, 0xa6, 0x4d, 0x18, 0xb8, 0x6b, 0x5b, 0xc4, 0x15, 0xba, 0xf0, 0x23, 0x1a,
+ 0x20, 0xb3, 0xa6, 0x7b, 0x81, 0xe2, 0xc5, 0x1c, 0xbd, 0xfa, 0x53, 0x0a, 0x40, 0x59, 0xf3, 0x34,
+ 0x6e, 0xba, 0xd1, 0x85, 0x75, 0xe0, 0xc5, 0xc8, 0xa9, 0x3a, 0x9c, 0xf0, 0x0c, 0xeb, 0x77, 0x8d,
+ 0xbb, 0xfe, 0xf0, 0x03, 0x69, 0x9d, 0x63, 0xaf, 0x19, 0x77, 0x09, 0x66, 0x70, 0xf4, 0x20, 0x8c,
+ 0x10, 0x4b, 0x77, 0x76, 0x5b, 0xf4, 0x60, 0xe1, 0x2a, 0x1e, 0xf6, 0x85, 0x2e, 0xfa, 0x85, 0x38,
+ 0x84, 0xab, 0x0f, 0x41, 0xf4, 0xca, 0xd5, 0x85, 0xf1, 0xf2, 0xdf, 0x2b, 0x70, 0xae, 0xdc, 0xd6,
+ 0xcc, 0xf9, 0x16, 0xdd, 0xa8, 0x9a, 0xb9, 0x64, 0x73, 0x1b, 0x00, 0x7a, 0x0f, 0x79, 0x1b, 0x0c,
+ 0xfb, 0x42, 0x4e, 0xdc, 0x75, 0xd4, 0x67, 0x94, 0x38, 0xa8, 0x81, 0x34, 0x18, 0x76, 0x7d, 0xb1,
+ 0xbb, 0xd0, 0x83, 0xd8, 0xed, 0x93, 0x08, 0xc4, 0xee, 0x00, 0x2d, 0x57, 0x7e, 0xb1, 0x05, 0xaa,
+ 0x11, 0x67, 0xdb, 0xd0, 0xc9, 0xbc, 0xae, 0xdb, 0x6d, 0xcb, 0x73, 0x85, 0x2b, 0xb8, 0x50, 0x7e,
+ 0xa5, 0xd5, 0xc0, 0x19, 0x2d, 0xd5, 0x2f, 0x29, 0xd0, 0xbf, 0xb8, 0x56, 0x2a, 0xa3, 0xef, 0x80,
+ 0xfe, 0x80, 0x65, 0xe4, 0x34, 0xf5, 0xa1, 0x78, 0xb8, 0x9e, 0x8e, 0xaf, 0xf7, 0x0a, 0x65, 0x38,
+ 0x0c, 0x2b, 0xda, 0x80, 0x41, 0xb2, 0x4d, 0x68, 0x57, 0x0b, 0x47, 0x82, 0x9f, 0xb1, 0xb4, 0x45,
+ 0x86, 0x11, 0x0b, 0xcc, 0xea, 0xa7, 0x14, 0x80, 0xb0, 0x0a, 0xfa, 0xee, 0xb4, 0xd3, 0xe9, 0xe6,
+ 0x11, 0x6a, 0x9f, 0x3b, 0x1f, 0x51, 0xea, 0xaf, 0x0f, 0xc0, 0x79, 0xda, 0x1d, 0xb1, 0x55, 0x0d,
+ 0xdb, 0xba, 0x49, 0x76, 0xbf, 0x69, 0x26, 0xff, 0x4d, 0x33, 0xf9, 0x23, 0x34, 0x93, 0x7f, 0x11,
+ 0xce, 0xd3, 0x2d, 0x27, 0xc0, 0x84, 0xd9, 0x0c, 0x55, 0x1d, 0xd2, 0xd2, 0x1c, 0x52, 0x67, 0xf7,
+ 0x81, 0x61, 0x6e, 0x05, 0x35, 0x9f, 0x55, 0x09, 0x67, 0xb7, 0x57, 0x9f, 0x82, 0xc9, 0x70, 0xef,
+ 0x8a, 0x8f, 0xea, 0xc1, 0xf8, 0x25, 0x73, 0xc4, 0x97, 0x98, 0x92, 0x17, 0x43, 0xf5, 0x9e, 0x02,
+ 0x93, 0x8b, 0x3b, 0x2d, 0xc3, 0x61, 0xfe, 0xf9, 0xdc, 0xcd, 0x04, 0x3d, 0x10, 0x7a, 0xa3, 0x28,
+ 0xd1, 0x57, 0xbc, 0xb8, 0x47, 0x0a, 0xda, 0x84, 0x09, 0xc2, 0x9a, 0xb3, 0x5b, 0xa0, 0xe6, 0xe5,
+ 0xd9, 0xde, 0x3c, 0x28, 0x45, 0x04, 0x0b, 0x8e, 0x61, 0x45, 0x35, 0x98, 0xd0, 0x4d, 0xcd, 0x75,
+ 0x8d, 0x4d, 0x43, 0x0f, 0xbd, 0xa8, 0x46, 0x16, 0x1e, 0x64, 0x32, 0x57, 0x04, 0x72, 0x6f, 0xaf,
+ 0x78, 0x46, 0xf4, 0x33, 0x0a, 0xc0, 0x31, 0x14, 0xea, 0x67, 0x0a, 0x30, 0xbe, 0xb8, 0xd3, 0xb2,
+ 0xdd, 0xb6, 0x43, 0x58, 0xd5, 0x13, 0xd0, 0x6b, 0x3d, 0x00, 0x43, 0x5b, 0x9a, 0x55, 0x37, 0x89,
+ 0x23, 0x8e, 0xdd, 0x60, 0x6e, 0x6f, 0xf0, 0x62, 0xec, 0xc3, 0xd1, 0xab, 0x00, 0xae, 0xbe, 0x45,
+ 0xea, 0x6d, 0xc6, 0x1c, 0xfb, 0xf2, 0x33, 0xc7, 0xc8, 0x18, 0x6b, 0x01, 0x4a, 0x21, 0xd2, 0x04,
+ 0xbf, 0xb1, 0x44, 0x4e, 0xfd, 0x13, 0x05, 0xa6, 0x22, 0xed, 0x4e, 0x40, 0x5d, 0xb3, 0x19, 0x55,
+ 0xd7, 0xcc, 0xf7, 0x3c, 0xd6, 0x0c, 0x2d, 0xcd, 0xc7, 0x0b, 0x70, 0x2e, 0x63, 0x4e, 0x12, 0xf6,
+ 0xbe, 0xca, 0x09, 0xd9, 0xfb, 0xb6, 0x61, 0xd4, 0xb3, 0x4d, 0xe1, 0xec, 0xe7, 0xcf, 0x40, 0xae,
+ 0x23, 0x78, 0x2d, 0x40, 0x13, 0x5a, 0xf3, 0x86, 0x65, 0x2e, 0x96, 0xe9, 0xa8, 0xbf, 0xa9, 0xc0,
+ 0x48, 0xa0, 0x15, 0x7e, 0x5d, 0x3d, 0xa8, 0x77, 0x1f, 0x47, 0x47, 0xfd, 0xbd, 0x02, 0x9c, 0x0d,
+ 0x70, 0xfb, 0x6c, 0xae, 0xe6, 0x51, 0xbe, 0x71, 0xb0, 0x6a, 0xe9, 0x62, 0xc4, 0x13, 0x61, 0x38,
+ 0xe9, 0x98, 0xd7, 0x6a, 0x3b, 0x2d, 0xdb, 0xf5, 0xe5, 0x60, 0x7e, 0x61, 0xe0, 0x45, 0xd8, 0x87,
+ 0xa1, 0x55, 0x18, 0x70, 0x29, 0x3d, 0x71, 0xd6, 0x1d, 0x72, 0x36, 0x98, 0x28, 0xcf, 0xfa, 0x8b,
+ 0x39, 0x1a, 0xf4, 0xaa, 0xcc, 0xc3, 0x07, 0xf2, 0x2b, 0x2f, 0xe9, 0x48, 0xea, 0x81, 0x24, 0x1c,
+ 0x3e, 0x7d, 0x74, 0x52, 0x16, 0xaa, 0xcb, 0x30, 0x29, 0x8c, 0x5a, 0xf9, 0xb6, 0xb1, 0x74, 0x82,
+ 0xde, 0x1d, 0xd9, 0x19, 0xf7, 0xc7, 0x4c, 0x6a, 0xa6, 0xe3, 0xf5, 0xc3, 0x1d, 0xa3, 0xba, 0x30,
+ 0x7c, 0x5d, 0x74, 0x12, 0xcd, 0x42, 0xc1, 0xf0, 0xd7, 0x02, 0x04, 0x8e, 0x42, 0xa5, 0x8c, 0x0b,
+ 0x46, 0x17, 0x1e, 0x21, 0xf2, 0xb1, 0xd4, 0xd7, 0xf9, 0x58, 0x52, 0xbf, 0x5e, 0x80, 0x69, 0x9f,
+ 0xaa, 0x3f, 0xc6, 0xb2, 0x78, 0x2d, 0x3f, 0xe0, 0x52, 0x74, 0xb0, 0xaa, 0xf1, 0x16, 0xf4, 0x33,
+ 0x06, 0x98, 0xeb, 0x15, 0x3d, 0x40, 0x48, 0xbb, 0x83, 0x19, 0x22, 0xf4, 0x01, 0x18, 0x34, 0xe9,
+ 0x0d, 0xc3, 0x77, 0xd5, 0xc8, 0xa5, 0x98, 0x4d, 0x1b, 0x2e, 0xbf, 0xb8, 0x88, 0x10, 0x66, 0xc1,
+ 0x43, 0x28, 0x2f, 0xc4, 0x82, 0xe6, 0xec, 0x63, 0x30, 0x2a, 0x55, 0x3b, 0x54, 0xfc, 0xb2, 0xcf,
+ 0x15, 0x60, 0xe6, 0x06, 0x31, 0x9b, 0xa9, 0xa6, 0x0f, 0x45, 0x18, 0xd0, 0xb7, 0x34, 0x87, 0x87,
+ 0xc6, 0x1b, 0xe3, 0x9b, 0xbc, 0x44, 0x0b, 0x30, 0x2f, 0xa7, 0x17, 0x8e, 0x88, 0x73, 0xda, 0x93,
+ 0xd2, 0x4c, 0x86, 0x31, 0x13, 0xdf, 0x1f, 0x04, 0x55, 0x0c, 0x07, 0x1e, 0xa9, 0x40, 0x8f, 0x97,
+ 0xf7, 0xd6, 0x6e, 0xad, 0xa6, 0xb9, 0xa5, 0xa1, 0xbb, 0x30, 0x6e, 0xeb, 0x06, 0x26, 0x2d, 0xdb,
+ 0x35, 0x3c, 0xdb, 0xd9, 0x15, 0x8b, 0x96, 0xeb, 0x68, 0xb9, 0x55, 0xaa, 0x84, 0x88, 0xf8, 0xf3,
+ 0x61, 0xa4, 0x08, 0x47, 0x49, 0xa9, 0x5f, 0x54, 0x60, 0xf4, 0x86, 0xb1, 0x41, 0x1c, 0x6e, 0xb7,
+ 0xcb, 0x34, 0x24, 0x91, 0x20, 0x6f, 0xa3, 0x69, 0x01, 0xde, 0xd0, 0x0e, 0x8c, 0x88, 0x73, 0x38,
+ 0xf0, 0x3a, 0xbc, 0x9e, 0xcf, 0x5e, 0x28, 0x20, 0x2d, 0xce, 0x37, 0xe9, 0xc3, 0xf7, 0x4b, 0x5c,
+ 0x1c, 0x12, 0x53, 0x5f, 0x85, 0xd3, 0x29, 0x8d, 0xe8, 0x42, 0x32, 0xd3, 0x55, 0xf1, 0xd1, 0xf8,
+ 0xdc, 0x8a, 0x2e, 0x24, 0x2b, 0x47, 0xe7, 0xa1, 0x8f, 0x58, 0x75, 0xf1, 0xc5, 0x0c, 0xed, 0xef,
+ 0x15, 0xfb, 0x16, 0xad, 0x3a, 0xa6, 0x65, 0x94, 0x89, 0x9b, 0x76, 0x44, 0x62, 0x63, 0x4c, 0x7c,
+ 0x59, 0x94, 0xe1, 0x00, 0xca, 0x2c, 0xbc, 0xe2, 0xc6, 0x4c, 0xf4, 0x66, 0x31, 0xb9, 0x19, 0xe3,
+ 0x2d, 0xbd, 0xd8, 0x50, 0xc5, 0xf9, 0xd4, 0xc2, 0x8c, 0x98, 0x90, 0x04, 0xc7, 0xc3, 0x09, 0xba,
+ 0xea, 0xaf, 0xf4, 0xc3, 0xa5, 0x1b, 0xb6, 0x63, 0xdc, 0xb5, 0x2d, 0x4f, 0x33, 0xab, 0x76, 0x3d,
+ 0xb4, 0x6f, 0x15, 0x47, 0xd6, 0xc7, 0x14, 0x38, 0xa7, 0xb7, 0xda, 0xfc, 0x66, 0xe2, 0x9b, 0x88,
+ 0x56, 0x89, 0x63, 0xd8, 0x79, 0x1d, 0x35, 0x98, 0x39, 0x6f, 0xa9, 0xba, 0x9e, 0x86, 0x12, 0x67,
+ 0xd1, 0x62, 0xfe, 0x22, 0x75, 0xfb, 0x8e, 0xc5, 0x3a, 0x57, 0xf3, 0xd8, 0x6c, 0xde, 0x0d, 0x17,
+ 0x21, 0xa7, 0xbf, 0x48, 0x39, 0x15, 0x23, 0xce, 0xa0, 0x84, 0x3e, 0x04, 0x67, 0x0c, 0xde, 0x39,
+ 0x4c, 0xb4, 0xba, 0x61, 0x11, 0xd7, 0xe5, 0xc6, 0xe6, 0x3d, 0x38, 0x44, 0x54, 0xd2, 0x10, 0xe2,
+ 0x74, 0x3a, 0xe8, 0x25, 0x00, 0x77, 0xd7, 0xd2, 0xc5, 0xfc, 0xe7, 0x33, 0x44, 0xe5, 0x22, 0x72,
+ 0x80, 0x05, 0x4b, 0x18, 0xe9, 0x45, 0xcb, 0x0b, 0x36, 0xe5, 0x20, 0x33, 0x26, 0x66, 0x17, 0xad,
+ 0x70, 0x0f, 0x85, 0x70, 0xf5, 0x53, 0x0a, 0x4c, 0x54, 0xac, 0xaa, 0xa9, 0xe9, 0x84, 0xdb, 0x55,
+ 0xba, 0xe8, 0x1a, 0x8c, 0xb8, 0xc1, 0x8b, 0x0c, 0xe7, 0x08, 0xe1, 0xf7, 0x19, 0xbc, 0xc5, 0x84,
+ 0x75, 0x98, 0x95, 0xb6, 0x61, 0x89, 0xc3, 0x6e, 0xc9, 0x76, 0x38, 0x22, 0xf1, 0xdd, 0x71, 0x2b,
+ 0xed, 0x24, 0x18, 0xa7, 0xb5, 0x51, 0x7f, 0x5e, 0x81, 0xe9, 0x68, 0x77, 0x84, 0x49, 0xc3, 0x8f,
+ 0x2b, 0x30, 0x1d, 0x71, 0xa6, 0x16, 0xe0, 0x5e, 0xe2, 0x3b, 0x55, 0x53, 0xf0, 0x71, 0x13, 0xdf,
+ 0x34, 0x08, 0x4e, 0xa5, 0xaf, 0xfe, 0x13, 0x05, 0x86, 0x44, 0xac, 0x47, 0xf4, 0xd6, 0x98, 0xf6,
+ 0x3c, 0x38, 0xda, 0x62, 0x1a, 0xf4, 0x5d, 0x66, 0x9f, 0x21, 0x8e, 0x26, 0x71, 0xca, 0xe4, 0x52,
+ 0xbf, 0x0a, 0xc2, 0xe1, 0x39, 0x17, 0xb1, 0xd3, 0xf0, 0x9f, 0x66, 0x24, 0x62, 0xea, 0x6b, 0x0a,
+ 0x4c, 0x25, 0x5a, 0x75, 0x21, 0x8e, 0x9e, 0xa0, 0xc5, 0xea, 0x57, 0xfa, 0xe9, 0x96, 0xf4, 0x28,
+ 0xbf, 0x37, 0xb9, 0x62, 0xfb, 0x04, 0xee, 0xbf, 0x0f, 0xc2, 0x88, 0xd1, 0x6c, 0xb6, 0x3d, 0xf6,
+ 0x88, 0x38, 0x10, 0x6a, 0x8b, 0x2b, 0x7e, 0x21, 0x0e, 0xe1, 0xc8, 0x12, 0x92, 0x16, 0x3f, 0x05,
+ 0x97, 0xf3, 0xad, 0x9c, 0x3c, 0xc0, 0x39, 0x2a, 0x15, 0x71, 0x71, 0x28, 0x4d, 0x10, 0xfb, 0x3e,
+ 0x05, 0xc0, 0xf5, 0x1c, 0xc3, 0x6a, 0xd0, 0x42, 0x21, 0x8d, 0xe1, 0x23, 0x20, 0x5b, 0x0b, 0x90,
+ 0x72, 0xe2, 0x61, 0xfc, 0xc7, 0x00, 0x80, 0x25, 0xca, 0x68, 0x5e, 0x08, 0xa1, 0xfc, 0xc8, 0x7c,
+ 0x7b, 0x4c, 0xdc, 0xbe, 0x94, 0x62, 0x09, 0xcb, 0x09, 0x85, 0x52, 0xea, 0xec, 0xa3, 0x30, 0x12,
+ 0xd0, 0x3b, 0x48, 0xa8, 0x1b, 0x93, 0x84, 0xba, 0xd9, 0x27, 0xe0, 0x54, 0xac, 0xbb, 0x87, 0x92,
+ 0x09, 0xff, 0x54, 0x01, 0x14, 0x1d, 0xfd, 0x09, 0x68, 0x0e, 0x1a, 0x51, 0xcd, 0xc1, 0x42, 0xef,
+ 0x4b, 0x96, 0xa1, 0x3a, 0xf8, 0x59, 0x04, 0x2c, 0x14, 0x6e, 0x10, 0x1a, 0x5a, 0x9c, 0xfc, 0x54,
+ 0x50, 0x09, 0x3d, 0xc0, 0xc5, 0x97, 0xdb, 0x83, 0xa0, 0x72, 0x33, 0x86, 0x2b, 0x14, 0x54, 0xe2,
+ 0x10, 0x9c, 0xa0, 0x8b, 0x3e, 0xa1, 0xc0, 0xa4, 0x16, 0x0d, 0x85, 0xeb, 0xcf, 0x4c, 0xae, 0x00,
+ 0x5d, 0xb1, 0xb0, 0xba, 0x61, 0x5f, 0x62, 0x00, 0x17, 0x27, 0xc8, 0xa2, 0x47, 0x60, 0x4c, 0x6b,
+ 0x19, 0xf3, 0xed, 0xba, 0x41, 0x6f, 0x9e, 0x7e, 0xc4, 0x50, 0xa6, 0x0d, 0x99, 0xaf, 0x56, 0x82,
+ 0x72, 0x1c, 0xa9, 0x15, 0xc4, 0x9c, 0x2d, 0x85, 0x86, 0xc3, 0xbd, 0xc4, 0x9c, 0x15, 0x73, 0x18,
+ 0xc6, 0x9c, 0x15, 0x53, 0x27, 0x13, 0x41, 0x16, 0x80, 0x6d, 0xd4, 0x75, 0x41, 0x72, 0x30, 0xff,
+ 0x1b, 0xc8, 0xad, 0x4a, 0xb9, 0x24, 0x28, 0x32, 0xf1, 0x21, 0xfc, 0x8d, 0x25, 0x0a, 0xe8, 0xd3,
+ 0x0a, 0x8c, 0x0b, 0xde, 0x2d, 0x68, 0x0e, 0xb1, 0x25, 0x7a, 0x21, 0xef, 0x7e, 0x89, 0xed, 0xc9,
+ 0x39, 0x2c, 0x23, 0xe7, 0x7c, 0x27, 0x08, 0x20, 0x10, 0x81, 0xe1, 0x68, 0x3f, 0x98, 0x0c, 0xe0,
+ 0x46, 0x1e, 0xa1, 0x44, 0x07, 0x87, 0xf3, 0xcb, 0x00, 0xb5, 0x14, 0x7c, 0xc2, 0xc9, 0x28, 0x05,
+ 0x82, 0x53, 0xe9, 0x53, 0xb9, 0xf6, 0xd4, 0x1d, 0xcd, 0xd3, 0xb7, 0x4a, 0x9a, 0xbe, 0xc5, 0xde,
+ 0x20, 0xb9, 0x3b, 0x65, 0xce, 0x7d, 0xfd, 0x5c, 0x14, 0xd5, 0xc2, 0xe9, 0xfd, 0xbd, 0xe2, 0xa9,
+ 0x58, 0x21, 0x8e, 0x13, 0x44, 0x36, 0x0c, 0x3b, 0x22, 0x1e, 0xbc, 0xf0, 0x80, 0xcf, 0x17, 0x02,
+ 0x3d, 0x1e, 0x5c, 0x9e, 0xdf, 0x8c, 0xfc, 0x5f, 0x38, 0x20, 0x82, 0x1a, 0x70, 0x89, 0xdf, 0x0d,
+ 0xe7, 0x2d, 0xdb, 0xda, 0x6d, 0xda, 0x6d, 0x77, 0xbe, 0xed, 0x6d, 0x11, 0xcb, 0xf3, 0x55, 0xe1,
+ 0xa3, 0xec, 0x18, 0x65, 0x4e, 0x73, 0x8b, 0x9d, 0x2a, 0xe2, 0xce, 0x78, 0xd0, 0xf3, 0x30, 0xcc,
+ 0xde, 0xe9, 0xd6, 0xd6, 0x96, 0x99, 0x67, 0xe6, 0xe1, 0xc5, 0x65, 0x36, 0x84, 0x45, 0x81, 0x03,
+ 0x07, 0xd8, 0xd0, 0x6d, 0x18, 0x32, 0x79, 0x40, 0x7f, 0xe6, 0xa1, 0x99, 0x93, 0x29, 0xc6, 0x93,
+ 0x03, 0xf0, 0x0b, 0xb4, 0xf8, 0x81, 0x7d, 0x0a, 0xa8, 0x05, 0x57, 0xea, 0x64, 0x53, 0x6b, 0x9b,
+ 0xde, 0xaa, 0xed, 0x61, 0xe6, 0xa1, 0x16, 0x68, 0x3c, 0x7d, 0x27, 0xdc, 0x09, 0x16, 0x83, 0x8d,
+ 0xf9, 0xfe, 0x95, 0x0f, 0xa8, 0x8b, 0x0f, 0xc4, 0x86, 0x76, 0xe1, 0x3e, 0x51, 0x87, 0xb9, 0xc4,
+ 0xe9, 0x5b, 0x74, 0x96, 0x93, 0x44, 0x4f, 0x31, 0xa2, 0xdf, 0xb2, 0xbf, 0x57, 0xbc, 0xaf, 0x7c,
+ 0x70, 0x75, 0xdc, 0x0d, 0x4e, 0xe6, 0x65, 0x44, 0x62, 0x4f, 0x40, 0x33, 0x93, 0xf9, 0xe7, 0x38,
+ 0xfe, 0x9c, 0xc4, 0xcd, 0xe1, 0xe2, 0xa5, 0x38, 0x41, 0x13, 0x7d, 0x41, 0x81, 0x19, 0xd7, 0x73,
+ 0xda, 0xba, 0xd7, 0x76, 0x48, 0x3d, 0xb6, 0x43, 0xa7, 0x58, 0x87, 0x72, 0x09, 0x70, 0xb5, 0x0c,
+ 0x9c, 0xcc, 0x1d, 0x7c, 0x26, 0x0b, 0x8a, 0x33, 0xfb, 0x82, 0x3e, 0xaf, 0xc0, 0xb9, 0x28, 0x90,
+ 0xde, 0xe9, 0x79, 0x3f, 0x51, 0xfe, 0x47, 0x96, 0x5a, 0x3a, 0x4a, 0x7e, 0x83, 0xcf, 0x00, 0xe2,
+ 0xac, 0x8e, 0xc4, 0x5f, 0xc6, 0x4f, 0x9f, 0xf0, 0xcb, 0xf8, 0xec, 0xd3, 0x80, 0x92, 0xc7, 0xc7,
+ 0x41, 0x72, 0xe0, 0xb0, 0x2c, 0x07, 0x7e, 0x76, 0x00, 0x2e, 0xd0, 0x53, 0x29, 0xbc, 0xfd, 0xac,
+ 0x68, 0x96, 0xd6, 0x78, 0x7d, 0x4a, 0x4c, 0x5f, 0x54, 0xe0, 0xdc, 0x56, 0xba, 0x6a, 0x47, 0xdc,
+ 0xbf, 0x9e, 0xc9, 0xa5, 0x82, 0xeb, 0xa4, 0x2d, 0xe2, 0x0c, 0xbb, 0x63, 0x15, 0x9c, 0xd5, 0x29,
+ 0xf4, 0x34, 0x4c, 0x5a, 0x76, 0x9d, 0x94, 0x2a, 0x65, 0xbc, 0xa2, 0xb9, 0xb7, 0x6b, 0xbe, 0xa1,
+ 0xce, 0x00, 0xff, 0x5e, 0x57, 0x63, 0x30, 0x9c, 0xa8, 0x8d, 0xb6, 0x01, 0xb5, 0xec, 0xfa, 0xe2,
+ 0x36, 0x4f, 0x7c, 0xd1, 0x9b, 0xc9, 0x2c, 0x33, 0x16, 0xa8, 0x26, 0xb0, 0xe1, 0x14, 0x0a, 0x4c,
+ 0x37, 0x45, 0x3b, 0xb3, 0x62, 0x5b, 0x86, 0x67, 0x3b, 0x2c, 0xc0, 0x41, 0x4f, 0x2a, 0x1a, 0xa6,
+ 0x9b, 0x5a, 0x4d, 0xc5, 0x88, 0x33, 0x28, 0xa9, 0xff, 0x4d, 0x81, 0x53, 0x74, 0x5b, 0x54, 0x1d,
+ 0x7b, 0x67, 0xf7, 0xf5, 0xb8, 0x21, 0x1f, 0x10, 0x36, 0x8b, 0x5c, 0xb7, 0x73, 0x46, 0xb2, 0x57,
+ 0x1c, 0x61, 0x7d, 0x0e, 0x4d, 0x14, 0x65, 0xb5, 0x72, 0x5f, 0xb6, 0x5a, 0x59, 0xfd, 0x74, 0x81,
+ 0xdf, 0x5c, 0x7c, 0xb5, 0xee, 0xeb, 0xf2, 0x3b, 0x7c, 0x14, 0xc6, 0x69, 0xd9, 0x8a, 0xb6, 0x53,
+ 0x2d, 0x3f, 0x6b, 0x9b, 0xbe, 0x37, 0x36, 0xd3, 0xb5, 0xdf, 0x94, 0x01, 0x38, 0x5a, 0x0f, 0x3d,
+ 0x0e, 0x43, 0x2d, 0x1e, 0x27, 0x4c, 0xdc, 0x99, 0xaf, 0x70, 0xc3, 0x3e, 0x56, 0x74, 0x6f, 0xaf,
+ 0x38, 0x15, 0x3e, 0xf1, 0xfa, 0xd1, 0xca, 0xfc, 0x06, 0xea, 0xaf, 0x9c, 0x05, 0x86, 0xdc, 0x24,
+ 0xde, 0xeb, 0x71, 0x4e, 0x1e, 0x82, 0x51, 0xbd, 0xd5, 0x2e, 0x2d, 0xd5, 0x9e, 0x69, 0xdb, 0x4c,
+ 0x17, 0xc2, 0xf2, 0xc3, 0x50, 0xee, 0x5d, 0xaa, 0xae, 0xfb, 0xc5, 0x58, 0xae, 0x43, 0xb9, 0x83,
+ 0xde, 0x6a, 0x0b, 0x7e, 0x5b, 0x95, 0xfd, 0x55, 0x18, 0x77, 0x28, 0x55, 0xd7, 0x23, 0x30, 0x9c,
+ 0xa8, 0x8d, 0x3e, 0x04, 0x63, 0x44, 0x7c, 0xb8, 0x37, 0x34, 0xa7, 0x2e, 0xf8, 0x42, 0x25, 0xef,
+ 0xe0, 0x83, 0xa9, 0xf5, 0xb9, 0x01, 0xbf, 0x01, 0x2e, 0x4a, 0x24, 0x70, 0x84, 0x20, 0x7a, 0x11,
+ 0xce, 0xfb, 0xbf, 0xe9, 0x2a, 0xdb, 0xf5, 0x38, 0xa3, 0x18, 0xe0, 0x66, 0x33, 0x8b, 0x59, 0x95,
+ 0x70, 0x76, 0x7b, 0xf4, 0x73, 0x0a, 0x9c, 0x0d, 0xa0, 0x86, 0x65, 0x34, 0xdb, 0x4d, 0x4c, 0x74,
+ 0x53, 0x33, 0x9a, 0xe2, 0xde, 0xf7, 0xdc, 0x91, 0x0d, 0x34, 0x8a, 0x9e, 0x33, 0xab, 0x74, 0x18,
+ 0xce, 0xe8, 0x12, 0x7a, 0x4d, 0x81, 0x2b, 0x3e, 0xa8, 0xea, 0x10, 0xd7, 0x6d, 0x3b, 0x24, 0x8c,
+ 0x05, 0x20, 0xa6, 0x64, 0x28, 0x17, 0xef, 0x64, 0x02, 0xf0, 0xe2, 0x01, 0xb8, 0xf1, 0x81, 0xd4,
+ 0xe5, 0xed, 0x52, 0xb3, 0x37, 0x3d, 0x71, 0x51, 0x3c, 0xae, 0xed, 0x42, 0x49, 0xe0, 0x08, 0x41,
+ 0xf4, 0xf3, 0x0a, 0x9c, 0x93, 0x0b, 0xe4, 0xdd, 0xc2, 0x6f, 0x88, 0xcf, 0x1f, 0x59, 0x67, 0x62,
+ 0xf8, 0xb9, 0x84, 0x97, 0x01, 0xc4, 0x59, 0xbd, 0xa2, 0x6c, 0xbb, 0xc9, 0x36, 0x26, 0xbf, 0x45,
+ 0x0e, 0x70, 0xb6, 0xcd, 0xf7, 0xaa, 0x8b, 0x7d, 0x18, 0x7a, 0x04, 0xc6, 0x5a, 0x76, 0xbd, 0x6a,
+ 0xd4, 0x5d, 0x16, 0xc3, 0x8c, 0xdd, 0xf5, 0xfa, 0xf8, 0x74, 0x54, 0xed, 0x7a, 0xb5, 0x52, 0xe6,
+ 0xe5, 0x38, 0x52, 0x0b, 0xcd, 0x01, 0x6c, 0x6a, 0x86, 0x59, 0xbb, 0xa3, 0xb5, 0x6e, 0xf9, 0x41,
+ 0x71, 0x98, 0x2e, 0x62, 0x29, 0x28, 0xc5, 0x52, 0x0d, 0xba, 0x7e, 0x94, 0xef, 0x60, 0xc2, 0xc3,
+ 0x4e, 0xb3, 0xeb, 0xd1, 0x51, 0xac, 0x9f, 0x8f, 0x90, 0x77, 0xf8, 0xa6, 0x44, 0x02, 0x47, 0x08,
+ 0xa2, 0x8f, 0x29, 0x30, 0xe1, 0xee, 0xba, 0x1e, 0x69, 0x06, 0x7d, 0x38, 0x75, 0xd4, 0x7d, 0x60,
+ 0x3a, 0xf1, 0x5a, 0x84, 0x08, 0x8e, 0x11, 0x65, 0xe1, 0x85, 0x9a, 0x5a, 0x83, 0x5c, 0x2f, 0xdd,
+ 0x30, 0x1a, 0x5b, 0x41, 0x74, 0x97, 0x2a, 0x71, 0x74, 0x62, 0x79, 0xec, 0x62, 0x35, 0x20, 0xc2,
+ 0x0b, 0x65, 0x57, 0xc3, 0x9d, 0x70, 0xa0, 0x97, 0x60, 0x56, 0x80, 0x97, 0xed, 0x3b, 0x09, 0x0a,
+ 0x3c, 0x8a, 0x0f, 0x33, 0x80, 0xac, 0x64, 0xd6, 0xc2, 0x1d, 0x30, 0xa0, 0x0a, 0x9c, 0x76, 0x89,
+ 0xc3, 0xde, 0x04, 0x79, 0x44, 0xc8, 0x6a, 0xdb, 0x34, 0x5d, 0x76, 0xb5, 0x11, 0x2e, 0x3f, 0xb5,
+ 0x24, 0x18, 0xa7, 0xb5, 0x41, 0x4f, 0x04, 0x6e, 0xc1, 0xbb, 0xb4, 0xe0, 0x99, 0x6a, 0x8d, 0xdd,
+ 0x44, 0x06, 0xb8, 0xa6, 0x04, 0x47, 0x41, 0x38, 0x5e, 0x97, 0x9e, 0xe6, 0x7e, 0xd1, 0x42, 0xdb,
+ 0x71, 0xbd, 0x99, 0x69, 0xd6, 0x98, 0x9d, 0xe6, 0x58, 0x06, 0xe0, 0x68, 0x3d, 0xf4, 0x38, 0x4c,
+ 0xb8, 0x44, 0xd7, 0xed, 0x66, 0x4b, 0xdc, 0x93, 0x67, 0xce, 0xb0, 0xde, 0xf3, 0x15, 0x8c, 0x40,
+ 0x70, 0xac, 0x26, 0xda, 0x85, 0xd3, 0x41, 0x08, 0xdd, 0x65, 0xbb, 0xb1, 0xa2, 0xed, 0x30, 0xe1,
+ 0xf8, 0x6c, 0x9e, 0x10, 0x0f, 0x7c, 0xba, 0x4a, 0x49, 0x74, 0x38, 0x8d, 0x06, 0x5a, 0x86, 0xe9,
+ 0x58, 0xf1, 0x92, 0x61, 0x12, 0x77, 0xe6, 0x1c, 0x1b, 0x36, 0x53, 0x76, 0x95, 0x52, 0xe0, 0x38,
+ 0xb5, 0x15, 0xba, 0x05, 0x67, 0x5a, 0x8e, 0xed, 0x11, 0xdd, 0xbb, 0x49, 0x05, 0x02, 0x53, 0x0c,
+ 0xd0, 0x9d, 0x99, 0x61, 0x73, 0xc1, 0xde, 0x43, 0xab, 0x69, 0x15, 0x70, 0x7a, 0x3b, 0xf4, 0x59,
+ 0x05, 0x2e, 0xbb, 0x9e, 0x43, 0xb4, 0xa6, 0x61, 0x35, 0x4a, 0xb6, 0x65, 0x11, 0xc6, 0x98, 0x2a,
+ 0xf5, 0xd0, 0x63, 0xee, 0x7c, 0xae, 0x53, 0x44, 0xdd, 0xdf, 0x2b, 0x5e, 0xae, 0x75, 0xc4, 0x8c,
+ 0x0f, 0xa0, 0x8c, 0x5e, 0x05, 0x68, 0x92, 0xa6, 0xed, 0xec, 0x52, 0x8e, 0x34, 0x33, 0x9b, 0xff,
+ 0xbe, 0xbb, 0x12, 0x60, 0xe1, 0x9f, 0x7f, 0xe4, 0x25, 0x37, 0x04, 0x62, 0x89, 0x1c, 0x9d, 0x6a,
+ 0xca, 0x6f, 0x45, 0x14, 0x2b, 0xe9, 0xa3, 0xb9, 0xc0, 0x56, 0x8e, 0x4d, 0xf5, 0x4a, 0x5a, 0x05,
+ 0x9c, 0xde, 0x0e, 0xb9, 0x30, 0xc5, 0xbe, 0x50, 0x71, 0x92, 0x5f, 0x2f, 0xcd, 0x37, 0xc8, 0xcc,
+ 0xc5, 0x5c, 0x93, 0x4b, 0x65, 0xff, 0xa9, 0x4a, 0x1c, 0x19, 0x4e, 0xe2, 0x0f, 0x89, 0x6a, 0x3b,
+ 0x21, 0xd1, 0x4b, 0xbd, 0x12, 0x95, 0x90, 0xe1, 0x24, 0x7e, 0x75, 0xaf, 0x00, 0x67, 0x52, 0x4f,
+ 0x49, 0xca, 0x3c, 0xf8, 0x14, 0xcf, 0xfb, 0xf9, 0xbf, 0xc4, 0xb3, 0x27, 0x63, 0x1e, 0x2b, 0x51,
+ 0x10, 0x8e, 0xd7, 0xa5, 0x32, 0x2c, 0xa3, 0xb6, 0x54, 0x0b, 0xdb, 0x17, 0x42, 0x19, 0xb6, 0x12,
+ 0x83, 0xe1, 0x44, 0x6d, 0x54, 0x12, 0xf3, 0xb1, 0x54, 0xab, 0xd0, 0x6b, 0xa0, 0xbb, 0xe4, 0x10,
+ 0xff, 0x76, 0x10, 0x8e, 0x4f, 0x06, 0xe2, 0x64, 0x7d, 0x3a, 0x0a, 0xfa, 0x43, 0xee, 0x45, 0x7f,
+ 0x38, 0x8a, 0xd5, 0x28, 0x08, 0xc7, 0xeb, 0xfa, 0xf7, 0xf4, 0x48, 0x17, 0x06, 0xc2, 0x51, 0xac,
+ 0xc6, 0x60, 0x38, 0x51, 0x5b, 0xfd, 0xb3, 0x7e, 0xb8, 0xaf, 0x0b, 0xc9, 0x12, 0x35, 0xd3, 0xa7,
+ 0xfb, 0xf0, 0x3c, 0xaf, 0xbb, 0xe5, 0x69, 0x65, 0x2c, 0xcf, 0xe1, 0xe9, 0x75, 0xbb, 0x9c, 0x6e,
+ 0xd6, 0x72, 0x1e, 0x9e, 0x64, 0xf7, 0xcb, 0xdf, 0x4c, 0x5f, 0xfe, 0x9c, 0xb3, 0x7a, 0xe0, 0x76,
+ 0x69, 0x65, 0x6c, 0x97, 0x9c, 0xb3, 0xda, 0xc5, 0xf6, 0xfa, 0xf3, 0x7e, 0xb8, 0xbf, 0x1b, 0x29,
+ 0x37, 0xe7, 0xfe, 0x4a, 0xe1, 0x2d, 0xc7, 0xba, 0xbf, 0xb2, 0xfc, 0xb9, 0x8f, 0x71, 0x7f, 0x75,
+ 0x64, 0x9f, 0xc7, 0xb3, 0xbf, 0xb2, 0x66, 0xf5, 0xb8, 0xf6, 0x57, 0xd6, 0xac, 0x76, 0xb1, 0xbf,
+ 0xfe, 0x26, 0x7e, 0x3e, 0x04, 0xa2, 0x76, 0x05, 0xfa, 0xf4, 0x56, 0x3b, 0x27, 0x93, 0x62, 0x56,
+ 0x86, 0xa5, 0xea, 0x3a, 0xa6, 0x38, 0x10, 0x86, 0x41, 0xbe, 0x7f, 0x72, 0xb2, 0x20, 0x66, 0x39,
+ 0xca, 0xb7, 0x24, 0x16, 0x98, 0xe8, 0x54, 0x91, 0xd6, 0x16, 0x69, 0x12, 0x47, 0x33, 0x6b, 0x9e,
+ 0xed, 0x68, 0x8d, 0xbc, 0xdc, 0x86, 0xbf, 0xa0, 0xc4, 0x70, 0xe1, 0x04, 0x76, 0x3a, 0x21, 0x2d,
+ 0xa3, 0x9e, 0x93, 0xbf, 0xb0, 0x09, 0xa9, 0x56, 0xca, 0x98, 0xe2, 0x50, 0x7f, 0x7d, 0x18, 0xa4,
+ 0xe0, 0xf4, 0xe8, 0x93, 0x0a, 0x4c, 0xe9, 0xf1, 0x98, 0x9c, 0xbd, 0xd8, 0x43, 0x25, 0x02, 0x7c,
+ 0xf2, 0x2d, 0x9f, 0x28, 0xc6, 0x49, 0xb2, 0xe8, 0xc3, 0x0a, 0x57, 0xf2, 0x05, 0xaf, 0x79, 0x62,
+ 0x5a, 0xaf, 0x1f, 0xd1, 0xbb, 0x77, 0xa8, 0x2d, 0x0c, 0x9f, 0x58, 0xa3, 0x04, 0xd1, 0x6b, 0x0a,
+ 0x9c, 0xb9, 0x9d, 0xf6, 0x36, 0x21, 0x26, 0xff, 0x56, 0xde, 0xae, 0x64, 0x3c, 0x76, 0x70, 0x09,
+ 0x32, 0xb5, 0x02, 0x4e, 0xef, 0x48, 0x30, 0x4b, 0x81, 0xba, 0x56, 0x7c, 0xa7, 0xb9, 0x67, 0x29,
+ 0xa6, 0xf7, 0x0d, 0x67, 0x29, 0x00, 0xe0, 0x28, 0x41, 0xd4, 0x82, 0x91, 0xdb, 0xbe, 0x8e, 0x5c,
+ 0xe8, 0xc5, 0x4a, 0x79, 0xa9, 0x4b, 0x8a, 0x76, 0x6e, 0xef, 0x15, 0x14, 0xe2, 0x90, 0x08, 0xda,
+ 0x82, 0xa1, 0xdb, 0x9c, 0x57, 0x08, 0x7d, 0xd6, 0x7c, 0xcf, 0xb7, 0x7f, 0xae, 0x56, 0x11, 0x45,
+ 0xd8, 0x47, 0x2f, 0xfb, 0x12, 0x0c, 0x1f, 0xe0, 0xe2, 0xf6, 0x59, 0x05, 0xce, 0x6c, 0x13, 0xc7,
+ 0x33, 0xf4, 0xf8, 0xcb, 0xd0, 0x48, 0x7e, 0x0d, 0xc5, 0xb3, 0x69, 0x08, 0xf9, 0x36, 0x49, 0x05,
+ 0xe1, 0xf4, 0x2e, 0xa0, 0x67, 0xa1, 0x9f, 0x78, 0x7a, 0x5d, 0x04, 0x70, 0x7e, 0x77, 0x5e, 0x97,
+ 0x5d, 0xee, 0xf7, 0x42, 0xff, 0xc3, 0x0c, 0x9f, 0xfa, 0x57, 0x0a, 0x24, 0x74, 0xd3, 0xe8, 0x87,
+ 0x14, 0x18, 0xdb, 0x24, 0x9a, 0xd7, 0x76, 0xc8, 0x75, 0x61, 0x13, 0xda, 0x77, 0x75, 0xf4, 0xe1,
+ 0x67, 0x8f, 0x42, 0x25, 0x3e, 0xb7, 0x24, 0x21, 0xe6, 0xc6, 0x2a, 0x41, 0xc2, 0x09, 0x19, 0x84,
+ 0x23, 0x3d, 0x98, 0x7d, 0x0a, 0xa6, 0x12, 0x0d, 0x0f, 0xf5, 0x4c, 0xf9, 0x6b, 0x0a, 0xa4, 0xe5,
+ 0x36, 0x47, 0x2f, 0xc1, 0x80, 0x56, 0xaf, 0x07, 0x29, 0x2e, 0x1f, 0xcb, 0x67, 0x37, 0x55, 0x97,
+ 0x23, 0x05, 0xb1, 0x9f, 0x98, 0xa3, 0x45, 0x4b, 0x80, 0xb4, 0xc8, 0xbb, 0xf4, 0x4a, 0x18, 0xa2,
+ 0x82, 0x3d, 0xa7, 0xcd, 0x27, 0xa0, 0x38, 0xa5, 0x85, 0xfa, 0x71, 0x05, 0x50, 0x32, 0x45, 0x09,
+ 0x72, 0x60, 0x58, 0xec, 0x5f, 0x7f, 0x95, 0xca, 0x39, 0xbd, 0xe9, 0x22, 0xae, 0xa1, 0xa1, 0x11,
+ 0x9e, 0x28, 0x70, 0x71, 0x40, 0x47, 0xfd, 0x3b, 0x05, 0xc2, 0x34, 0x78, 0xe8, 0x9d, 0x30, 0x5a,
+ 0x27, 0xae, 0xee, 0x18, 0x2d, 0x2f, 0x74, 0x24, 0x0d, 0x1c, 0xd2, 0xca, 0x21, 0x08, 0xcb, 0xf5,
+ 0x90, 0x0a, 0x83, 0x9e, 0xe6, 0xde, 0xae, 0x94, 0xc5, 0x65, 0x8f, 0x1d, 0xcd, 0x6b, 0xac, 0x04,
+ 0x0b, 0x48, 0x18, 0x3a, 0xb6, 0xaf, 0x8b, 0xd0, 0xb1, 0x68, 0xf3, 0x08, 0xe2, 0xe4, 0xa2, 0x83,
+ 0x63, 0xe4, 0xaa, 0x3f, 0x53, 0x80, 0x53, 0xb4, 0xca, 0x8a, 0x66, 0x58, 0x1e, 0xb1, 0x98, 0xdb,
+ 0x54, 0xce, 0x49, 0x68, 0xc0, 0xb8, 0x17, 0x71, 0x5a, 0x3e, 0xbc, 0x53, 0x6d, 0x60, 0xe9, 0x15,
+ 0x75, 0x55, 0x8e, 0xe2, 0x45, 0x8f, 0xf9, 0x7e, 0x6b, 0xfc, 0x5a, 0x7c, 0x9f, 0xbf, 0x55, 0x99,
+ 0x33, 0xda, 0x3d, 0xe1, 0x01, 0x1e, 0xe4, 0x4e, 0x8c, 0xb8, 0xa8, 0x3d, 0x0a, 0xe3, 0xc2, 0x43,
+ 0x82, 0xc7, 0x00, 0x16, 0xd7, 0x62, 0x76, 0xac, 0x2c, 0xc9, 0x00, 0x1c, 0xad, 0xa7, 0xfe, 0x61,
+ 0x01, 0xa2, 0x19, 0x1a, 0xf3, 0xce, 0x52, 0x32, 0x00, 0x72, 0xe1, 0xd8, 0x02, 0x20, 0xf3, 0x1c,
+ 0xe5, 0xcc, 0x9c, 0x5b, 0xbc, 0xb3, 0xcb, 0xf9, 0x89, 0x59, 0x39, 0x0e, 0x6a, 0x84, 0xd3, 0xda,
+ 0x7f, 0xe8, 0x69, 0x7d, 0xa7, 0xb0, 0xfc, 0x1d, 0x88, 0x84, 0xa1, 0xf6, 0x2d, 0x7f, 0xa7, 0x22,
+ 0x0d, 0x25, 0x2f, 0xbb, 0x79, 0x10, 0x39, 0x4e, 0xe8, 0xba, 0x88, 0x10, 0xd9, 0xee, 0x9a, 0xed,
+ 0x69, 0x26, 0x9b, 0x4e, 0xa1, 0x74, 0x5d, 0x91, 0x01, 0x38, 0x5a, 0x4f, 0x5d, 0x85, 0x37, 0x2f,
+ 0xdb, 0x5a, 0x7d, 0x41, 0x33, 0xe9, 0xd6, 0x75, 0x84, 0x59, 0x9e, 0xcb, 0x4e, 0xe6, 0xaa, 0x63,
+ 0x7b, 0xb6, 0x6e, 0x9b, 0xf4, 0xdc, 0xd4, 0x82, 0x58, 0xc1, 0xec, 0x21, 0xd2, 0x3f, 0x37, 0x45,
+ 0xac, 0x5d, 0xec, 0xc3, 0xd5, 0xdf, 0x51, 0x60, 0x48, 0xe4, 0x3d, 0xe9, 0xc2, 0xb1, 0x74, 0x13,
+ 0x06, 0xd8, 0xed, 0xa8, 0x17, 0xa9, 0xb4, 0xb6, 0x65, 0xdb, 0x5e, 0x24, 0x61, 0x12, 0x4f, 0x39,
+ 0xc6, 0x92, 0x44, 0x72, 0xf4, 0xcc, 0x1e, 0xd5, 0xd1, 0xb7, 0x0c, 0x8f, 0x30, 0xb3, 0x1b, 0xb1,
+ 0xf1, 0xb9, 0x3d, 0xaa, 0x54, 0x8e, 0x23, 0xb5, 0xd4, 0xff, 0x3a, 0x00, 0x57, 0xfc, 0x1c, 0x2e,
+ 0x71, 0x51, 0x2d, 0xe0, 0xb9, 0xbb, 0x41, 0x52, 0x19, 0x16, 0x14, 0xdf, 0xd7, 0xa9, 0xe6, 0xbb,
+ 0x25, 0x9f, 0x93, 0xd2, 0xc6, 0xc8, 0xe8, 0x70, 0x1a, 0x0d, 0x1e, 0x7d, 0x9d, 0x15, 0xdf, 0x20,
+ 0x9a, 0xe9, 0x6d, 0xf9, 0xb4, 0x0b, 0xbd, 0x44, 0x5f, 0x4f, 0xe2, 0xc3, 0xa9, 0x54, 0x98, 0x49,
+ 0x87, 0x9f, 0xcc, 0xc6, 0x21, 0x9a, 0x6c, 0x4f, 0xd2, 0x83, 0xbb, 0xd1, 0x4a, 0x2a, 0x46, 0x9c,
+ 0x41, 0x89, 0xa9, 0x1b, 0xb5, 0x1d, 0xa6, 0xbd, 0xc0, 0xc4, 0x73, 0x0c, 0x96, 0xf8, 0x2a, 0x78,
+ 0xab, 0x58, 0x89, 0x82, 0x70, 0xbc, 0x2e, 0x7a, 0x1c, 0x26, 0x98, 0x89, 0x4c, 0x18, 0xce, 0x73,
+ 0x20, 0x0c, 0xea, 0xb4, 0x1a, 0x81, 0xe0, 0x58, 0x4d, 0xf4, 0x3d, 0x0a, 0x4c, 0x1b, 0xb2, 0x33,
+ 0x8d, 0x3f, 0xfa, 0x7c, 0x99, 0x51, 0xd8, 0xf3, 0x92, 0xbf, 0x8d, 0x53, 0xd0, 0xe2, 0x54, 0x62,
+ 0x68, 0x19, 0xa6, 0x85, 0x47, 0x74, 0x74, 0x0f, 0xf0, 0x58, 0x6f, 0x6c, 0x4d, 0xcb, 0x29, 0x70,
+ 0x9c, 0xda, 0x4a, 0xfd, 0x48, 0x01, 0xc6, 0x0e, 0x99, 0xc4, 0xb4, 0x2d, 0xc9, 0x1c, 0x3d, 0xf8,
+ 0x2d, 0xca, 0x54, 0xbb, 0x10, 0x3b, 0xd0, 0xf3, 0x30, 0xd1, 0x66, 0x13, 0xe1, 0x47, 0x42, 0x13,
+ 0xdf, 0xf4, 0xb7, 0xd1, 0x95, 0x5b, 0x8f, 0x40, 0xee, 0xed, 0x15, 0x67, 0x65, 0xf4, 0x51, 0x28,
+ 0x8e, 0xe1, 0x51, 0x7f, 0xa3, 0x00, 0x48, 0xae, 0xbe, 0x64, 0x6a, 0xdb, 0xb6, 0x83, 0x3e, 0xaf,
+ 0xc0, 0x98, 0x2e, 0xa7, 0x8d, 0xe2, 0x02, 0xd6, 0xf3, 0xbd, 0x0e, 0x96, 0xa3, 0x9f, 0x93, 0xf3,
+ 0x41, 0x71, 0x41, 0xd8, 0x77, 0xb7, 0x1e, 0x93, 0x41, 0xf7, 0x62, 0xbf, 0x71, 0xa4, 0x4f, 0xb3,
+ 0x1f, 0x53, 0x60, 0x2a, 0x81, 0x29, 0x45, 0x32, 0x7e, 0x21, 0x1a, 0x03, 0xfd, 0x48, 0x12, 0x44,
+ 0xca, 0xf2, 0xf5, 0x4f, 0x0e, 0xc0, 0xe9, 0x94, 0x15, 0x65, 0x26, 0x36, 0x24, 0x26, 0x5d, 0xf6,
+ 0x62, 0x62, 0x93, 0x90, 0x54, 0x03, 0x13, 0x9b, 0x38, 0x04, 0x27, 0xe8, 0xa2, 0x67, 0xa1, 0x4f,
+ 0x77, 0x0c, 0xb1, 0x69, 0x1f, 0xcd, 0x35, 0x05, 0xb8, 0xb2, 0x30, 0x2a, 0x28, 0xf6, 0x95, 0x70,
+ 0x05, 0x53, 0x84, 0xf4, 0x2c, 0x96, 0x8f, 0x11, 0x5f, 0x60, 0x65, 0x67, 0xb1, 0x7c, 0xda, 0xb8,
+ 0x38, 0x5a, 0x0f, 0x3d, 0x0f, 0x33, 0xe2, 0xa6, 0xea, 0x47, 0x32, 0xb1, 0x2d, 0xd7, 0xa3, 0x1c,
+ 0xdf, 0x13, 0x32, 0x05, 0xb3, 0x7e, 0xbd, 0x99, 0x51, 0x07, 0x67, 0xb6, 0x46, 0xdf, 0x0d, 0x13,
+ 0x11, 0xee, 0xe1, 0x47, 0x25, 0xcb, 0xe9, 0x32, 0x23, 0x63, 0xe2, 0xbc, 0x32, 0x5a, 0x86, 0x63,
+ 0xd4, 0xd0, 0xff, 0xad, 0xc0, 0x54, 0xb0, 0x51, 0x77, 0xf9, 0x96, 0xf7, 0x33, 0xf8, 0x2d, 0x1d,
+ 0xcd, 0x17, 0x24, 0xa5, 0x57, 0x8d, 0x13, 0xc2, 0x49, 0xda, 0xea, 0x8f, 0x0e, 0x82, 0x9c, 0xd1,
+ 0x19, 0xad, 0xf4, 0xa2, 0x97, 0x0c, 0xf7, 0x80, 0xaf, 0x9b, 0x5c, 0x81, 0xbe, 0x46, 0xab, 0x9d,
+ 0x53, 0x31, 0x19, 0xa0, 0xbb, 0x4e, 0xd1, 0x35, 0x5a, 0x6d, 0xf4, 0x6c, 0xa0, 0xea, 0xcc, 0xa7,
+ 0x8c, 0x0c, 0x5c, 0x25, 0x63, 0xea, 0x4e, 0x9f, 0xbd, 0xf7, 0x67, 0xb2, 0xf7, 0x26, 0x0c, 0xb9,
+ 0x42, 0x0f, 0x3a, 0x90, 0x3f, 0x8c, 0xa4, 0x34, 0xd3, 0x42, 0xef, 0xc9, 0x35, 0x34, 0xbe, 0x5a,
+ 0xd4, 0xa7, 0x41, 0x2f, 0x82, 0x6d, 0x76, 0x2e, 0x89, 0x20, 0x49, 0xec, 0x22, 0xb8, 0xce, 0x4a,
+ 0xb0, 0x80, 0x24, 0x84, 0xb9, 0xa1, 0x6e, 0x84, 0x39, 0xf4, 0xb9, 0x38, 0xff, 0x1e, 0x66, 0xbb,
+ 0xef, 0x99, 0x1e, 0x87, 0xf3, 0x7f, 0x18, 0xe3, 0xfe, 0xbf, 0xc2, 0xc3, 0x4f, 0x5a, 0x2c, 0x74,
+ 0x1f, 0x0c, 0xb0, 0x28, 0x4a, 0x42, 0x0e, 0x08, 0x94, 0x1b, 0x2c, 0x8e, 0x0e, 0xe6, 0x30, 0x54,
+ 0x13, 0xa1, 0x03, 0xf3, 0x6d, 0x7a, 0x66, 0xdb, 0x28, 0xe8, 0x49, 0x71, 0x06, 0xaf, 0x44, 0x7c,
+ 0x22, 0xd3, 0xee, 0x10, 0xeb, 0x30, 0xd4, 0x34, 0x2c, 0x66, 0xee, 0x91, 0x4f, 0x89, 0xce, 0x4d,
+ 0xb0, 0x38, 0x0a, 0xec, 0xe3, 0x52, 0xff, 0xbc, 0x40, 0x19, 0x44, 0x78, 0xa9, 0xdf, 0xe5, 0x81,
+ 0x70, 0x85, 0xf7, 0xb5, 0x92, 0x5f, 0x09, 0x28, 0x21, 0x9d, 0x0f, 0x10, 0x72, 0x43, 0x85, 0xf0,
+ 0x37, 0x96, 0x88, 0x51, 0xd2, 0x9e, 0xd1, 0x24, 0xcf, 0x19, 0x56, 0xdd, 0xbe, 0x23, 0xa6, 0xb7,
+ 0x57, 0xd2, 0x6b, 0x01, 0x42, 0x4e, 0x3a, 0xfc, 0x8d, 0x25, 0x62, 0xf4, 0x48, 0x62, 0xc9, 0x38,
+ 0x2c, 0x96, 0x89, 0x57, 0xf4, 0x8d, 0xe7, 0xd9, 0x16, 0x76, 0xc7, 0xec, 0x48, 0x2a, 0x65, 0xd4,
+ 0xc1, 0x99, 0xad, 0xd5, 0x9f, 0x53, 0xe0, 0x4c, 0xea, 0x54, 0xa0, 0xeb, 0x30, 0x15, 0x9a, 0xc3,
+ 0xca, 0x42, 0xc2, 0x70, 0xc8, 0xe3, 0x6f, 0xc6, 0x2b, 0xe0, 0x64, 0x1b, 0x9e, 0xdf, 0x2c, 0x21,
+ 0x84, 0x08, 0x5b, 0x5a, 0xf9, 0xaa, 0x25, 0x83, 0x71, 0x5a, 0x1b, 0xf5, 0xc5, 0x48, 0x67, 0xc3,
+ 0xc9, 0xa2, 0x5f, 0xc6, 0x06, 0x69, 0x04, 0x3e, 0xe9, 0xc1, 0x97, 0xb1, 0x40, 0x0b, 0x31, 0x87,
+ 0xa1, 0x4b, 0x72, 0xa8, 0x8c, 0x80, 0xbb, 0xfb, 0xe1, 0x32, 0xd4, 0x5f, 0x53, 0xe0, 0xdc, 0x8a,
+ 0x66, 0xb5, 0x35, 0x93, 0x3b, 0xbf, 0x57, 0x6d, 0xdb, 0x14, 0xd3, 0xd4, 0x29, 0xdf, 0xba, 0xf2,
+ 0x7a, 0xc9, 0xb7, 0xfe, 0x7e, 0x38, 0x97, 0x61, 0x7f, 0x83, 0xca, 0x30, 0xe6, 0xde, 0xd1, 0x5a,
+ 0x0b, 0x64, 0x4b, 0xdb, 0x36, 0x44, 0x60, 0x2d, 0x6e, 0xa6, 0x3d, 0x56, 0x93, 0xca, 0xef, 0xc5,
+ 0x7e, 0xe3, 0x48, 0x2b, 0xd5, 0x03, 0x10, 0xe6, 0xfc, 0x86, 0xd5, 0x40, 0x9b, 0x30, 0xac, 0x99,
+ 0xc4, 0xf1, 0xc2, 0xe0, 0x91, 0xdf, 0x9e, 0x4b, 0x4f, 0x2b, 0x70, 0x70, 0xf7, 0x35, 0xff, 0x17,
+ 0x0e, 0x70, 0xab, 0xff, 0x48, 0x81, 0xb3, 0xe9, 0xa1, 0x94, 0xba, 0xb8, 0x16, 0x35, 0x61, 0xd4,
+ 0x09, 0x9b, 0x89, 0x8f, 0xf6, 0x5d, 0x72, 0x86, 0x0a, 0xc9, 0xf1, 0x86, 0x5e, 0x04, 0x4b, 0x8e,
+ 0xed, 0xfa, 0x3b, 0x37, 0x9e, 0xb4, 0x22, 0xd0, 0x8a, 0x49, 0x3d, 0xc1, 0x32, 0x7e, 0x96, 0x40,
+ 0x86, 0x52, 0x77, 0x5b, 0x9a, 0x4e, 0xea, 0x27, 0x9c, 0x53, 0xfd, 0x08, 0xb2, 0x36, 0xa4, 0xf7,
+ 0xfd, 0x78, 0x13, 0xc8, 0x64, 0xd0, 0x3c, 0x38, 0x81, 0x4c, 0x7a, 0xc3, 0x37, 0x48, 0x66, 0x83,
+ 0xf4, 0xce, 0x67, 0x38, 0xbe, 0xff, 0xe7, 0xc1, 0xac, 0xd1, 0x1e, 0x32, 0x31, 0xfb, 0xf6, 0x31,
+ 0x26, 0x66, 0x9f, 0xf8, 0x66, 0x52, 0xf6, 0x94, 0xa4, 0xec, 0xb1, 0x44, 0xe1, 0x83, 0x27, 0x94,
+ 0x28, 0xfc, 0x15, 0x18, 0x6c, 0x69, 0x0e, 0xb1, 0xfc, 0xb7, 0xdc, 0x4a, 0x3e, 0x43, 0x83, 0x70,
+ 0xa3, 0x85, 0x5c, 0x30, 0xf8, 0x24, 0xab, 0x8c, 0x00, 0x16, 0x84, 0x52, 0x82, 0xa7, 0x0c, 0x1f,
+ 0x57, 0x74, 0xc2, 0x30, 0x45, 0xf9, 0xc8, 0x71, 0xa4, 0x28, 0x57, 0xff, 0x56, 0x81, 0x8b, 0x9d,
+ 0xd8, 0x12, 0x53, 0xa0, 0xe8, 0xb1, 0xcf, 0xb0, 0x17, 0x05, 0x4a, 0x82, 0xdb, 0x06, 0x0a, 0x94,
+ 0x38, 0x04, 0x27, 0xe8, 0xa2, 0xf7, 0x02, 0xb2, 0x37, 0xb8, 0x5d, 0xcf, 0x75, 0x4a, 0x83, 0x7b,
+ 0xd3, 0x16, 0x98, 0xaf, 0x42, 0x90, 0xd7, 0xf2, 0x56, 0xa2, 0x06, 0x4e, 0x69, 0xa5, 0xfe, 0x4a,
+ 0x01, 0x60, 0x95, 0x78, 0x77, 0x6c, 0xe7, 0x36, 0x3d, 0xe3, 0x2f, 0x46, 0x9e, 0x0e, 0x86, 0xbf,
+ 0x71, 0xf1, 0x28, 0x2f, 0x42, 0x7f, 0xcb, 0xae, 0xbb, 0xe2, 0xfe, 0xc1, 0x3a, 0xc2, 0x5c, 0x35,
+ 0x58, 0x29, 0x2a, 0xc2, 0x00, 0x33, 0x7a, 0x12, 0x17, 0x68, 0xf6, 0xf0, 0xc0, 0x1e, 0x57, 0x30,
+ 0x2f, 0xa7, 0x1c, 0x52, 0xc4, 0x34, 0x70, 0xc5, 0xe3, 0xce, 0x18, 0x8f, 0x21, 0xce, 0xcb, 0x70,
+ 0x00, 0x45, 0x8f, 0x03, 0x18, 0xad, 0x25, 0xad, 0x69, 0x98, 0x86, 0xf8, 0x5c, 0x47, 0x98, 0x46,
+ 0x1c, 0x2a, 0x55, 0xbf, 0xf4, 0xde, 0x5e, 0x71, 0x58, 0xfc, 0xda, 0xc5, 0x52, 0x6d, 0xf5, 0x8b,
+ 0x0a, 0x4c, 0x86, 0x93, 0x27, 0xb6, 0x8a, 0xdf, 0x73, 0x1e, 0x0c, 0x38, 0xb3, 0xe7, 0x3c, 0x6c,
+ 0x7f, 0xe7, 0x9e, 0x73, 0x05, 0x56, 0x56, 0xcf, 0x1f, 0x82, 0x51, 0xc2, 0x43, 0x1e, 0x55, 0xca,
+ 0x98, 0xf3, 0xb8, 0x11, 0x7e, 0x9d, 0x5b, 0x0c, 0x8b, 0xb1, 0x5c, 0x47, 0xfd, 0xfb, 0x3e, 0x18,
+ 0x5b, 0x6d, 0x18, 0xd6, 0x8e, 0x1f, 0xdb, 0x29, 0x78, 0x78, 0x57, 0x8e, 0xe7, 0xe1, 0xfd, 0x79,
+ 0x98, 0x31, 0xe5, 0x67, 0x2e, 0x2e, 0x38, 0x69, 0x56, 0x23, 0x98, 0x01, 0x76, 0x8f, 0x59, 0xce,
+ 0xa8, 0x83, 0x33, 0x5b, 0x23, 0x0f, 0x06, 0x75, 0x3f, 0xbf, 0x62, 0xee, 0x78, 0x45, 0xf2, 0x5c,
+ 0xcc, 0xc9, 0xa1, 0x3b, 0x02, 0x9e, 0x27, 0xb6, 0xa7, 0xa0, 0x85, 0x3e, 0xaa, 0xc0, 0x19, 0xb2,
+ 0xc3, 0x43, 0xd7, 0xac, 0x39, 0xda, 0xe6, 0xa6, 0xa1, 0x0b, 0x8f, 0x3f, 0xbe, 0x13, 0x97, 0xf7,
+ 0xf7, 0x8a, 0x67, 0x16, 0xd3, 0x2a, 0xdc, 0xdb, 0x2b, 0x5e, 0x4b, 0x8d, 0x24, 0xc4, 0x56, 0x33,
+ 0xb5, 0x09, 0x4e, 0x27, 0x35, 0xfb, 0x18, 0x8c, 0x1e, 0xc2, 0x4f, 0x3c, 0x12, 0x2f, 0xe8, 0x57,
+ 0x0b, 0x30, 0x46, 0xb7, 0xdb, 0xb2, 0xad, 0x6b, 0x66, 0x79, 0xb5, 0x86, 0x1e, 0x88, 0x87, 0x49,
+ 0x0c, 0x9e, 0x18, 0x13, 0xa1, 0x12, 0x97, 0x61, 0x7a, 0xd3, 0x76, 0x74, 0xb2, 0x56, 0xaa, 0xae,
+ 0xd9, 0xc2, 0xf8, 0xac, 0xbc, 0x5a, 0x13, 0xf7, 0x3a, 0xf6, 0xe4, 0xb1, 0x94, 0x02, 0xc7, 0xa9,
+ 0xad, 0xd0, 0x2d, 0x38, 0x13, 0x96, 0xaf, 0xb7, 0xb8, 0xc3, 0x02, 0x45, 0xd7, 0x17, 0x3a, 0x5c,
+ 0x2c, 0xa5, 0x55, 0xc0, 0xe9, 0xed, 0x90, 0x06, 0x17, 0xc4, 0xdb, 0xca, 0x92, 0xed, 0xdc, 0xd1,
+ 0x9c, 0x7a, 0x14, 0x6d, 0x7f, 0x98, 0xab, 0xbc, 0x9c, 0x5d, 0x0d, 0x77, 0xc2, 0xa1, 0xfe, 0x9d,
+ 0x02, 0xd1, 0x20, 0x94, 0xe8, 0x3c, 0xf4, 0x39, 0x22, 0x7d, 0x9f, 0x08, 0xc6, 0x48, 0xaf, 0x08,
+ 0xb4, 0x0c, 0xcd, 0x01, 0x38, 0x61, 0x24, 0xcc, 0x42, 0x98, 0xd6, 0x42, 0x8a, 0x61, 0x29, 0xd5,
+ 0xa0, 0xa8, 0x3c, 0xad, 0x21, 0x18, 0x1e, 0x43, 0xb5, 0xa6, 0x35, 0x30, 0x2d, 0x63, 0xf9, 0x4b,
+ 0x8c, 0x06, 0x71, 0x7d, 0x75, 0x34, 0xcf, 0x5f, 0xc2, 0x4a, 0xb0, 0x80, 0x20, 0x0d, 0xc6, 0x5b,
+ 0x6d, 0x53, 0xc4, 0x53, 0xa2, 0x57, 0x1f, 0xae, 0x36, 0xbc, 0x9a, 0x96, 0x9c, 0x8f, 0xad, 0x7e,
+ 0x6a, 0x86, 0xbe, 0xaa, 0x8c, 0x02, 0x47, 0x31, 0xaa, 0x3f, 0x31, 0x08, 0x52, 0x78, 0x9d, 0x43,
+ 0x48, 0xa1, 0x3f, 0xad, 0xc0, 0xb4, 0x6e, 0x1a, 0xc4, 0xf2, 0x62, 0x91, 0x2a, 0xf8, 0xf1, 0xb1,
+ 0x9e, 0x2b, 0xee, 0x4f, 0x8b, 0x58, 0x95, 0xb2, 0x70, 0x6f, 0x29, 0xa5, 0x20, 0x17, 0x2e, 0x40,
+ 0x29, 0x10, 0x9c, 0xda, 0x19, 0x36, 0x1e, 0x56, 0x5e, 0x29, 0xcb, 0xd1, 0x33, 0x4b, 0xa2, 0x0c,
+ 0x07, 0x50, 0xca, 0x79, 0x1b, 0x8e, 0xdd, 0x6e, 0xb9, 0x25, 0xe6, 0xc5, 0xca, 0x17, 0x85, 0x71,
0xde, 0xeb, 0x61, 0x31, 0x96, 0xeb, 0xa0, 0x47, 0x60, 0x8c, 0xff, 0xac, 0x3a, 0x64, 0xd3, 0xd8,
- 0x11, 0x87, 0x12, 0x33, 0x9e, 0x5e, 0x97, 0xca, 0x71, 0xa4, 0x16, 0x8b, 0xdf, 0xe6, 0xba, 0x6d,
- 0xe2, 0xac, 0xe3, 0x65, 0x91, 0xe3, 0x99, 0xc7, 0x6f, 0xf3, 0x0b, 0x71, 0x08, 0x47, 0x3f, 0xa4,
+ 0x11, 0x87, 0x12, 0x53, 0x9e, 0x5e, 0x97, 0xca, 0x71, 0xa4, 0x16, 0x8b, 0xdf, 0xe6, 0xba, 0x6d,
+ 0xe2, 0xac, 0xe3, 0x65, 0x91, 0xe3, 0x99, 0xc7, 0x6f, 0xf3, 0x0b, 0x71, 0x08, 0x47, 0x3f, 0xa2,
0xc0, 0x84, 0x43, 0x5e, 0x69, 0x1b, 0x0e, 0x15, 0x61, 0x34, 0xa3, 0xe9, 0x8a, 0x18, 0x47, 0xb8,
- 0xb7, 0xb8, 0x4a, 0x73, 0x38, 0x82, 0x94, 0x33, 0xc8, 0xc0, 0x95, 0x23, 0x0a, 0xc4, 0xb1, 0x1e,
- 0xd0, 0xa9, 0x72, 0x8d, 0x86, 0x65, 0x58, 0x8d, 0x79, 0xb3, 0xe1, 0x8a, 0x44, 0x56, 0xdc, 0xe6,
+ 0xb7, 0xb8, 0x4a, 0x73, 0x38, 0x82, 0x94, 0x33, 0xc8, 0xc0, 0x94, 0x23, 0x0a, 0xc4, 0xb1, 0x1e,
+ 0xd0, 0xa9, 0x72, 0x8d, 0x86, 0x65, 0x58, 0x8d, 0x79, 0xb3, 0xe1, 0x8a, 0x44, 0x56, 0x5c, 0xe7,
0x18, 0x16, 0x63, 0xb9, 0x0e, 0x7a, 0x14, 0xc6, 0xdb, 0x2e, 0x65, 0x7b, 0x4d, 0xc2, 0xe7, 0x77,
- 0x24, 0xf4, 0x75, 0x59, 0x97, 0x01, 0x38, 0x5a, 0x0f, 0x3d, 0x0e, 0x13, 0x7e, 0x81, 0x98, 0x65,
- 0xe0, 0xd9, 0x54, 0xd8, 0xdd, 0x64, 0x04, 0x82, 0x63, 0x35, 0x67, 0xe7, 0xe1, 0x74, 0xca, 0x30,
- 0x0f, 0xc5, 0x5b, 0xff, 0xb7, 0x02, 0x67, 0xb8, 0xd4, 0xe5, 0x67, 0x87, 0xf6, 0x73, 0x5b, 0xa4,
- 0xa7, 0x89, 0x50, 0x8e, 0x35, 0x4d, 0xc4, 0xd7, 0x21, 0x1d, 0x86, 0xfa, 0xd3, 0x05, 0x78, 0xf3,
- 0x81, 0xdf, 0x25, 0xfa, 0x47, 0x0a, 0x8c, 0x92, 0x1d, 0xcf, 0xd1, 0x82, 0xa7, 0xfe, 0x74, 0x93,
- 0x6e, 0x1e, 0x0b, 0x13, 0x98, 0x5b, 0x0c, 0x09, 0xf1, 0x8d, 0x1b, 0xa8, 0x52, 0x12, 0x04, 0xcb,
- 0xfd, 0xa1, 0xdc, 0x96, 0x67, 0x1b, 0x92, 0x9d, 0xe2, 0x04, 0x17, 0x14, 0x90, 0xd9, 0x27, 0x61,
- 0x32, 0x8e, 0xf9, 0x50, 0x7b, 0xe5, 0x0b, 0x0a, 0xa4, 0x86, 0xe3, 0x44, 0x25, 0x98, 0xd2, 0xda,
- 0x9e, 0x1d, 0xb9, 0xd7, 0x13, 0xa2, 0x24, 0x73, 0xfa, 0x9e, 0x8f, 0x03, 0x71, 0xb2, 0x3e, 0x37,
- 0xc0, 0x5a, 0x6d, 0xcd, 0x8c, 0xa2, 0xe1, 0x02, 0x97, 0x30, 0xc0, 0x26, 0xc0, 0x38, 0xad, 0x8d,
- 0xfa, 0xcf, 0x14, 0x38, 0x93, 0x6a, 0x96, 0xec, 0xc2, 0x16, 0x97, 0xbe, 0xed, 0x0b, 0xc7, 0xb9,
- 0xed, 0xd5, 0x5f, 0x2a, 0xc0, 0x50, 0xd5, 0xb1, 0xe9, 0xd1, 0x76, 0x02, 0x16, 0x38, 0x2d, 0x62,
- 0x81, 0xcb, 0x65, 0x5f, 0x10, 0x9d, 0xcd, 0x34, 0xb9, 0x19, 0x31, 0x93, 0xdb, 0x7c, 0x2f, 0x44,
- 0x3a, 0xdb, 0xd8, 0x7e, 0x4f, 0x81, 0x51, 0x51, 0xf3, 0x04, 0x8c, 0x6a, 0xdf, 0x11, 0x35, 0xaa,
- 0xbd, 0xa7, 0x87, 0x71, 0x65, 0x58, 0xd1, 0x3e, 0xab, 0xc0, 0xb8, 0xa8, 0xb1, 0x42, 0x9a, 0x1b,
+ 0x24, 0xb4, 0x75, 0x59, 0x97, 0x01, 0x38, 0x5a, 0x0f, 0x3d, 0x0e, 0x13, 0x7e, 0x81, 0x98, 0x65,
+ 0xe0, 0xd9, 0x54, 0xd8, 0xdb, 0x64, 0x04, 0x82, 0x63, 0x35, 0x67, 0xe7, 0xe1, 0x74, 0xca, 0x30,
+ 0x0f, 0xc5, 0x5b, 0xff, 0x97, 0x02, 0x67, 0xb8, 0xd4, 0xe5, 0x67, 0x87, 0xf6, 0x73, 0x5b, 0xa4,
+ 0xa7, 0x89, 0x50, 0x8e, 0x35, 0x4d, 0xc4, 0x37, 0x20, 0x1d, 0x86, 0xfa, 0xb3, 0x05, 0x78, 0xf3,
+ 0x81, 0xdf, 0x25, 0xfa, 0xff, 0x14, 0x18, 0x25, 0x3b, 0x9e, 0xa3, 0x05, 0xae, 0xfe, 0x74, 0x93,
+ 0x6e, 0x1e, 0x0b, 0x13, 0x98, 0x5b, 0x0c, 0x09, 0xf1, 0x8d, 0x1b, 0x5c, 0xa5, 0x24, 0x08, 0x96,
+ 0xfb, 0x43, 0xb9, 0x2d, 0xcf, 0x36, 0x24, 0x1b, 0xc5, 0x09, 0x2e, 0x28, 0x20, 0xb3, 0x4f, 0xc2,
+ 0x64, 0x1c, 0xf3, 0xa1, 0xf6, 0xca, 0x17, 0x14, 0x48, 0x0d, 0xc7, 0x89, 0x4a, 0x30, 0xa5, 0xb5,
+ 0x3d, 0x3b, 0xf2, 0xae, 0x27, 0x44, 0x49, 0x66, 0xf4, 0x3d, 0x1f, 0x07, 0xe2, 0x64, 0x7d, 0xae,
+ 0x80, 0xb5, 0xda, 0x9a, 0x19, 0x45, 0xc3, 0x05, 0x2e, 0xa1, 0x80, 0x4d, 0x80, 0x71, 0x5a, 0x1b,
+ 0xf5, 0x9f, 0x2a, 0x70, 0x26, 0x55, 0x2d, 0xd9, 0x85, 0x2e, 0x2e, 0x7d, 0xdb, 0x17, 0x8e, 0x73,
+ 0xdb, 0xab, 0xbf, 0x5c, 0x80, 0xa1, 0xaa, 0x63, 0xd3, 0xa3, 0xed, 0x04, 0x34, 0x70, 0x5a, 0x44,
+ 0x03, 0x97, 0x4b, 0xbf, 0x20, 0x3a, 0x9b, 0xa9, 0x72, 0x33, 0x62, 0x2a, 0xb7, 0xf9, 0x5e, 0x88,
+ 0x74, 0xd6, 0xb1, 0x7d, 0x59, 0x81, 0x51, 0x51, 0xf3, 0x04, 0x94, 0x6a, 0xdf, 0x15, 0x55, 0xaa,
+ 0xbd, 0xa7, 0x87, 0x71, 0x65, 0x68, 0xd1, 0x3e, 0xab, 0xc0, 0xb8, 0xa8, 0xb1, 0x42, 0x9a, 0x1b,
0xc4, 0x41, 0x4b, 0x30, 0xe4, 0xb6, 0xd9, 0x42, 0x8a, 0x01, 0x5d, 0x90, 0xc5, 0x23, 0x67, 0x43,
0xd3, 0x69, 0xf7, 0x6b, 0xbc, 0x8a, 0x94, 0x09, 0x99, 0x17, 0x60, 0xbf, 0x31, 0xdd, 0xfb, 0x8e,
- 0x6d, 0x26, 0xc2, 0xd6, 0x63, 0xdb, 0x24, 0x98, 0x41, 0xa8, 0x9e, 0x47, 0xff, 0xfa, 0x3a, 0x1c,
- 0xd3, 0xf3, 0x28, 0xd8, 0xc5, 0xbc, 0x5c, 0xfd, 0xe2, 0x40, 0x30, 0xd9, 0x4c, 0xa9, 0xbf, 0x01,
- 0x23, 0xba, 0x43, 0x34, 0x8f, 0xd4, 0x17, 0x76, 0xbb, 0xe9, 0x1c, 0x93, 0x03, 0x4a, 0x7e, 0x0b,
- 0x1c, 0x36, 0xa6, 0x47, 0xae, 0xec, 0xe0, 0x59, 0x08, 0xa5, 0x93, 0x4c, 0xe7, 0xce, 0x6f, 0x85,
- 0x01, 0xfb, 0x8e, 0x15, 0x3c, 0x0e, 0xe9, 0x48, 0x98, 0x0d, 0xe5, 0x16, 0xad, 0x8d, 0x79, 0x23,
- 0x39, 0x6d, 0x43, 0x7f, 0x87, 0xb4, 0x0d, 0x26, 0x0c, 0x35, 0xd9, 0x32, 0xf4, 0x94, 0x18, 0x37,
- 0xb2, 0xa0, 0xe1, 0x12, 0xf1, 0xdf, 0x2e, 0xf6, 0x49, 0x50, 0xd1, 0xc9, 0xf2, 0x2d, 0x3a, 0xb2,
- 0xe8, 0x14, 0x98, 0x79, 0x70, 0x08, 0x47, 0xbb, 0xd1, 0x7c, 0x20, 0x43, 0xf9, 0xed, 0xa4, 0xa2,
- 0x7b, 0x52, 0x0a, 0x10, 0x3e, 0xf5, 0x59, 0x39, 0x41, 0xd0, 0x17, 0x14, 0x38, 0x57, 0x4f, 0x4f,
- 0xb8, 0x26, 0xae, 0xca, 0x73, 0x3d, 0xcc, 0xce, 0xc8, 0xe1, 0xb6, 0x50, 0x14, 0x13, 0x96, 0x95,
- 0xe4, 0x0d, 0x67, 0x75, 0x46, 0xfd, 0xde, 0xfe, 0xe0, 0x6b, 0x12, 0x96, 0x8e, 0x74, 0x3b, 0x94,
- 0x92, 0xc7, 0x0e, 0x85, 0xde, 0xe1, 0xa7, 0xff, 0xe2, 0xdb, 0xf5, 0x52, 0x3c, 0xfd, 0xd7, 0x98,
- 0x20, 0x1d, 0x49, 0xf9, 0xd5, 0x86, 0xd3, 0xae, 0xa7, 0x99, 0xa4, 0x66, 0x88, 0xcb, 0x41, 0xd7,
- 0xd3, 0x9a, 0xad, 0x1c, 0xf9, 0xb7, 0x78, 0xa0, 0x86, 0x24, 0x2a, 0x9c, 0x86, 0x1f, 0x7d, 0x37,
- 0x0b, 0xbe, 0xa7, 0x99, 0xec, 0xf2, 0x94, 0xe7, 0x20, 0x0d, 0x89, 0x1f, 0xde, 0xdd, 0x5d, 0x84,
- 0xd6, 0x4b, 0xc7, 0x87, 0x33, 0x29, 0xa1, 0x57, 0xe1, 0x0c, 0x3d, 0x00, 0xe7, 0x75, 0xcf, 0xd8,
- 0x36, 0xbc, 0xdd, 0xb0, 0x0b, 0x87, 0x4f, 0xba, 0xc5, 0xb4, 0xed, 0xe5, 0x34, 0x64, 0x38, 0x9d,
- 0x86, 0xfa, 0x37, 0x0a, 0xa0, 0xe4, 0x5e, 0x47, 0x26, 0x0c, 0xd7, 0xfd, 0xc8, 0x09, 0xca, 0x91,
- 0x64, 0xd5, 0x09, 0x8e, 0x90, 0x20, 0xe0, 0x42, 0x40, 0x01, 0xd9, 0x30, 0x72, 0x67, 0xcb, 0xf0,
- 0x88, 0x69, 0xb8, 0xde, 0x11, 0x25, 0xf1, 0x09, 0x62, 0xc2, 0x3f, 0xe7, 0x23, 0xc6, 0x21, 0x0d,
- 0xf5, 0x53, 0xfd, 0x30, 0x1c, 0x24, 0xd3, 0x3c, 0xd8, 0xcd, 0xba, 0x0d, 0x48, 0x97, 0x02, 0x02,
- 0xf6, 0x62, 0x33, 0x65, 0x32, 0x50, 0x29, 0x81, 0x0c, 0xa7, 0x10, 0x40, 0xaf, 0xc2, 0xb4, 0x61,
- 0x6d, 0x3a, 0x5a, 0x10, 0xee, 0xb0, 0xe4, 0x1b, 0xca, 0x72, 0x10, 0x66, 0x5a, 0x74, 0x25, 0x05,
- 0x1d, 0x4e, 0x25, 0x82, 0x08, 0x0c, 0xf1, 0x7c, 0xc6, 0xfe, 0xad, 0x4b, 0x2e, 0x5b, 0x3d, 0x97,
- 0x35, 0x43, 0xf6, 0xee, 0xcb, 0x9e, 0x3e, 0x6e, 0x1e, 0x9c, 0x96, 0xff, 0xef, 0x5f, 0x48, 0x89,
- 0x7d, 0x5f, 0xca, 0x4f, 0x2f, 0xbc, 0xdb, 0xe2, 0xc1, 0x69, 0xa3, 0x85, 0x38, 0x4e, 0x50, 0xfd,
- 0x1d, 0x05, 0x06, 0x78, 0x0c, 0xb0, 0xe3, 0x17, 0x35, 0xdf, 0x1f, 0x11, 0x35, 0x9f, 0xc8, 0x33,
- 0x48, 0xd6, 0xd5, 0xcc, 0x8c, 0xfc, 0xbf, 0xad, 0xc0, 0x08, 0xab, 0x71, 0x02, 0xb2, 0xdf, 0x4b,
- 0x51, 0xd9, 0xef, 0xb1, 0xdc, 0xa3, 0xc9, 0x90, 0xfc, 0x7e, 0xa7, 0x4f, 0x8c, 0x85, 0x89, 0x56,
- 0x15, 0x38, 0x2d, 0x1e, 0xc6, 0x2e, 0x1b, 0x9b, 0x84, 0x6e, 0xf1, 0xb2, 0xb6, 0xeb, 0x8a, 0xa7,
- 0x1a, 0x3c, 0xe8, 0x4c, 0x12, 0x8c, 0xd3, 0xda, 0xa0, 0x5f, 0x51, 0xa8, 0x10, 0xe3, 0x39, 0x86,
- 0xde, 0xd3, 0x65, 0x70, 0xd0, 0xb7, 0xb9, 0x15, 0x8e, 0x8c, 0xeb, 0xa6, 0xeb, 0xa1, 0x34, 0xc3,
- 0x4a, 0xef, 0xed, 0x15, 0x8b, 0x29, 0x36, 0xe3, 0x30, 0x2b, 0xb5, 0xeb, 0x7d, 0xf4, 0x2f, 0x3a,
- 0x56, 0x61, 0xda, 0x98, 0xdf, 0x63, 0x74, 0x03, 0x06, 0x5c, 0xdd, 0x6e, 0xf9, 0x4f, 0xab, 0xef,
- 0x4b, 0xb3, 0x0d, 0xc6, 0xcd, 0x82, 0xc1, 0x04, 0xd7, 0x68, 0x4b, 0xcc, 0x11, 0xcc, 0xbe, 0x0c,
- 0x63, 0x72, 0xcf, 0x53, 0x74, 0xdf, 0x72, 0xd4, 0x63, 0xee, 0x90, 0xce, 0x61, 0xb2, 0xae, 0xfc,
- 0x47, 0x7d, 0x30, 0x88, 0x49, 0x43, 0xa4, 0x4c, 0x3b, 0x40, 0xe7, 0x34, 0xfc, 0xf4, 0xbf, 0x85,
- 0xfc, 0xef, 0xf0, 0xe4, 0xa4, 0x38, 0x2f, 0xd8, 0x96, 0x34, 0x07, 0x72, 0x06, 0x60, 0x64, 0x05,
- 0x89, 0xa4, 0xfa, 0xf2, 0x3b, 0xd4, 0xf2, 0x81, 0x75, 0x93, 0x3a, 0x0a, 0xfd, 0xa0, 0x02, 0x48,
- 0xd3, 0x75, 0xe2, 0xba, 0x98, 0xb8, 0x74, 0xee, 0xb9, 0xb0, 0xca, 0xb9, 0x6c, 0xbe, 0xa8, 0xd8,
- 0x71, 0x6c, 0xa1, 0xd8, 0x96, 0x00, 0xb9, 0x38, 0x85, 0x78, 0x2f, 0xe9, 0xac, 0x7e, 0x5f, 0x81,
- 0xb1, 0x48, 0xb6, 0xb0, 0x66, 0x68, 0x4b, 0xcf, 0xef, 0xb2, 0xe3, 0xbf, 0xfe, 0xba, 0xd0, 0xa1,
- 0x12, 0xb7, 0xcf, 0xdf, 0x0a, 0xd2, 0x5d, 0x1c, 0x4d, 0x62, 0x31, 0xf5, 0xd3, 0x0a, 0x9c, 0xf5,
- 0x07, 0x14, 0x8d, 0x6b, 0x8e, 0xae, 0xc2, 0xb0, 0xd6, 0x32, 0x98, 0xa1, 0x57, 0x36, 0x95, 0xcf,
- 0x57, 0x2b, 0xac, 0x0c, 0x07, 0xd0, 0x48, 0x8e, 0xe5, 0xc2, 0x81, 0x39, 0x96, 0xdf, 0x22, 0x65,
- 0x8d, 0x1e, 0x08, 0x65, 0x97, 0x80, 0x30, 0x77, 0xe6, 0x54, 0xdf, 0x05, 0x23, 0xb5, 0xda, 0x0d,
- 0xbe, 0xa4, 0x87, 0xb8, 0xf1, 0x51, 0x3f, 0xd1, 0x07, 0xe3, 0x22, 0x41, 0x83, 0xc1, 0x4c, 0x40,
- 0x27, 0x70, 0xce, 0xad, 0xc1, 0x88, 0x1b, 0xdc, 0x61, 0x14, 0xb2, 0xf9, 0x54, 0x70, 0x2d, 0x11,
- 0xcf, 0xb2, 0x17, 0x5e, 0x5f, 0x84, 0x88, 0xd0, 0x4d, 0x18, 0x7c, 0x85, 0xf2, 0x5c, 0xff, 0x5b,
- 0xed, 0x8a, 0xf5, 0x05, 0x1f, 0x22, 0x63, 0xd7, 0x2e, 0x16, 0x28, 0x90, 0xcb, 0x9e, 0x27, 0x32,
- 0x21, 0xb0, 0x97, 0x50, 0x9d, 0x91, 0x99, 0x0d, 0x72, 0xc6, 0x8f, 0x89, 0x57, 0x8e, 0xec, 0x17,
- 0x0e, 0x08, 0xb1, 0x14, 0xa1, 0x91, 0x16, 0x6f, 0x90, 0x14, 0xa1, 0x91, 0x3e, 0x67, 0x1c, 0xd7,
- 0x8f, 0xc1, 0x99, 0xd4, 0xc9, 0x38, 0x58, 0xc4, 0x56, 0xff, 0x79, 0x01, 0xfa, 0x6b, 0x84, 0xd4,
- 0x4f, 0x60, 0x67, 0xbe, 0x14, 0x91, 0xc0, 0xbe, 0x35, 0x77, 0x92, 0xd2, 0x2c, 0x4b, 0xdf, 0x66,
- 0xcc, 0xd2, 0xf7, 0x64, 0x6e, 0x0a, 0x9d, 0xcd, 0x7c, 0x7f, 0x55, 0x80, 0x21, 0x5a, 0xad, 0xbc,
- 0x5a, 0x43, 0x4d, 0x69, 0x2b, 0x17, 0xf2, 0x8b, 0xcf, 0x02, 0xdd, 0x41, 0x9b, 0x98, 0x7e, 0x39,
- 0x86, 0x48, 0xfc, 0x22, 0x06, 0x59, 0x39, 0x02, 0x72, 0x22, 0xf6, 0x04, 0x23, 0xea, 0xe7, 0x95,
- 0xc1, 0x01, 0x21, 0x74, 0x47, 0xd2, 0x49, 0xfb, 0xf3, 0xfb, 0xee, 0xa6, 0x13, 0xed, 0xa0, 0x9e,
- 0xaa, 0x9f, 0x50, 0xe0, 0x54, 0xac, 0x55, 0x17, 0x4a, 0xe3, 0xb1, 0x30, 0x40, 0xf5, 0x6b, 0x0a,
- 0xfd, 0xc6, 0x52, 0x46, 0xd0, 0x45, 0x8f, 0xc2, 0x04, 0x60, 0x85, 0x8e, 0x09, 0xc0, 0x2e, 0x42,
- 0x3f, 0x95, 0x8c, 0x64, 0x9f, 0x1d, 0x2a, 0x30, 0x61, 0x56, 0x8a, 0x74, 0x98, 0xd0, 0xa5, 0x14,
- 0xee, 0x64, 0x53, 0xf0, 0xce, 0xae, 0x58, 0x71, 0x70, 0xdd, 0x58, 0x8a, 0xa0, 0xc0, 0x31, 0x94,
- 0xea, 0x6f, 0x29, 0x30, 0x4c, 0x87, 0x79, 0x02, 0xcc, 0xf1, 0xdb, 0xa3, 0xcc, 0xf1, 0xdd, 0x79,
- 0xf7, 0x54, 0x06, 0x4f, 0xfc, 0xeb, 0x02, 0xb0, 0x0c, 0xc6, 0xc2, 0xbf, 0x48, 0xf2, 0x1c, 0x52,
- 0x32, 0x7c, 0x9e, 0xae, 0x08, 0xc7, 0xa3, 0x98, 0x51, 0x5a, 0x72, 0x3e, 0x7a, 0x5b, 0xc4, 0xb7,
- 0x28, 0x22, 0x5c, 0xa4, 0xf8, 0x17, 0xdd, 0x85, 0x71, 0x77, 0xcb, 0xb6, 0xbd, 0x72, 0xf8, 0xf1,
- 0xe4, 0xbe, 0x80, 0x60, 0x8f, 0xc5, 0xfd, 0xa1, 0xf0, 0xab, 0xdc, 0x9a, 0x8c, 0x1b, 0x47, 0x49,
- 0xa1, 0x39, 0x80, 0x0d, 0xd3, 0xd6, 0x6f, 0x73, 0xd7, 0x26, 0xfe, 0x38, 0x98, 0x39, 0x4f, 0x2c,
- 0x04, 0xa5, 0x58, 0xaa, 0xd1, 0x93, 0x17, 0xd7, 0xd7, 0x14, 0x3e, 0xd3, 0x87, 0xf8, 0x46, 0x4f,
- 0xd0, 0x11, 0xee, 0xad, 0x30, 0xe8, 0x30, 0x1d, 0x41, 0xac, 0x58, 0xf0, 0xf1, 0x71, 0xcd, 0x01,
- 0x0b, 0x28, 0xdd, 0x1e, 0x5c, 0xf1, 0xe9, 0x0f, 0x2f, 0x1c, 0x64, 0x75, 0x45, 0xfd, 0x25, 0x31,
- 0xcc, 0x20, 0x09, 0x76, 0x0b, 0xc6, 0x99, 0x66, 0x11, 0xcb, 0xbe, 0xfd, 0x8e, 0x2e, 0xbf, 0x11,
- 0xb9, 0x69, 0xe8, 0x96, 0x1b, 0x29, 0xc6, 0x51, 0x02, 0xe8, 0x51, 0x18, 0xf7, 0x47, 0xc7, 0xbd,
- 0x63, 0x0b, 0xe1, 0x0b, 0xcd, 0xaa, 0x0c, 0xc0, 0xd1, 0x7a, 0xea, 0x67, 0x0a, 0x70, 0x89, 0xf7,
- 0x9d, 0x59, 0x5e, 0xca, 0xa4, 0x45, 0xac, 0x3a, 0xb1, 0xf4, 0x5d, 0x26, 0x67, 0xd7, 0xed, 0x06,
- 0x7a, 0x15, 0x06, 0xef, 0x10, 0x52, 0x0f, 0xae, 0x30, 0x9e, 0xcb, 0x9f, 0x43, 0x3c, 0x83, 0xc4,
- 0x73, 0x0c, 0x3d, 0xbf, 0x0d, 0xe6, 0xff, 0x63, 0x41, 0x92, 0x12, 0x6f, 0x39, 0xf6, 0x46, 0x20,
- 0x0e, 0x1e, 0x3d, 0xf1, 0x2a, 0x43, 0xcf, 0x89, 0xf3, 0xff, 0xb1, 0x20, 0xa9, 0x56, 0xe1, 0xbe,
- 0x2e, 0x9a, 0x1e, 0x46, 0xec, 0x3f, 0x08, 0x23, 0x1f, 0xfd, 0x61, 0x30, 0xfe, 0x89, 0x02, 0xf7,
- 0x4b, 0x28, 0x17, 0x77, 0xa8, 0x26, 0x52, 0xd2, 0x5a, 0x9a, 0x4e, 0x75, 0x7d, 0x16, 0xa3, 0xee,
- 0x50, 0x59, 0x7b, 0x3f, 0xa1, 0xc0, 0x10, 0xf7, 0xc8, 0xf3, 0xd9, 0xef, 0x4b, 0x3d, 0x4e, 0x79,
- 0x66, 0x97, 0xfc, 0x6c, 0x66, 0xfe, 0xd8, 0xf8, 0x6f, 0x17, 0xfb, 0xf4, 0xd5, 0x7f, 0x3d, 0x00,
- 0xdf, 0xdc, 0x3d, 0x22, 0xf4, 0x35, 0x45, 0xce, 0x36, 0xce, 0x6d, 0xe4, 0xcd, 0xe3, 0xed, 0x7c,
- 0x60, 0x0d, 0x12, 0x06, 0x86, 0xe7, 0x12, 0x09, 0xc9, 0x8f, 0xc8, 0xd0, 0x14, 0x0e, 0x0c, 0xfd,
- 0x53, 0x05, 0xc6, 0xe8, 0xb1, 0x14, 0x30, 0x17, 0xbe, 0x4c, 0xad, 0x63, 0x1e, 0xe9, 0xaa, 0x44,
- 0x32, 0x16, 0xd7, 0x4a, 0x06, 0xe1, 0x48, 0xdf, 0xd0, 0x7a, 0xf4, 0xfa, 0x8f, 0xab, 0x88, 0x97,
- 0xd3, 0xe4, 0x92, 0xc3, 0xa4, 0xfb, 0x9f, 0x35, 0x61, 0x22, 0x3a, 0xf3, 0xc7, 0x69, 0x26, 0x9b,
- 0x7d, 0x0a, 0xa6, 0x12, 0xa3, 0x3f, 0x94, 0x41, 0xe6, 0x67, 0x07, 0xa1, 0x28, 0x4d, 0x75, 0x5a,
- 0x78, 0x1a, 0xf4, 0x39, 0x05, 0x46, 0x35, 0xcb, 0x12, 0x8e, 0x4d, 0xfe, 0xfe, 0xad, 0xf7, 0xb8,
- 0xaa, 0x69, 0xa4, 0xe6, 0xe6, 0x43, 0x32, 0x31, 0xcf, 0x1d, 0x09, 0x82, 0xe5, 0xde, 0x74, 0xf0,
- 0xce, 0x2d, 0x9c, 0x98, 0x77, 0x2e, 0xfa, 0xa0, 0x7f, 0x10, 0xf7, 0xe5, 0x0f, 0x54, 0x71, 0xc0,
- 0xdc, 0xb0, 0x73, 0x3d, 0xc3, 0x2a, 0xf9, 0xfd, 0x0a, 0x3b, 0x64, 0xc3, 0x28, 0x42, 0xe2, 0x4c,
- 0xca, 0xe5, 0x64, 0x79, 0x60, 0x88, 0xa2, 0xe0, 0xec, 0x0e, 0x8b, 0x70, 0x94, 0x3c, 0xfa, 0x11,
- 0x05, 0xc6, 0xee, 0xda, 0x96, 0x66, 0x0a, 0x3f, 0x6b, 0x71, 0x4d, 0xf3, 0xfe, 0xe3, 0x99, 0x97,
- 0x80, 0x0c, 0xf7, 0xad, 0x94, 0x4b, 0x70, 0xa4, 0x1b, 0xb3, 0x4f, 0xc2, 0x64, 0x7c, 0x8b, 0x1d,
- 0xea, 0x73, 0x59, 0x83, 0x07, 0x0f, 0xd1, 0x9d, 0x2e, 0x4f, 0x36, 0xf5, 0xd7, 0xfb, 0x23, 0x27,
- 0x65, 0xe6, 0xea, 0x77, 0x61, 0x0a, 0x7f, 0x2d, 0xf6, 0xad, 0x72, 0x0e, 0x6c, 0x1c, 0xd7, 0x7e,
- 0x3c, 0xda, 0x0f, 0xb6, 0xef, 0xe4, 0x3e, 0xd8, 0xd7, 0xdb, 0x17, 0xd3, 0xf3, 0xce, 0x5c, 0xe0,
- 0xaa, 0xbe, 0x58, 0xb0, 0x30, 0x17, 0x13, 0x8b, 0xc3, 0x69, 0xb8, 0x86, 0x1f, 0x4d, 0x5a, 0x92,
- 0xd8, 0x9e, 0xe5, 0xc5, 0xd8, 0x87, 0xab, 0xcb, 0x91, 0xb3, 0x60, 0xcd, 0x6e, 0xd9, 0xa6, 0xdd,
- 0xd8, 0x9d, 0xbf, 0xa3, 0x39, 0x04, 0xdb, 0x6d, 0x4f, 0x60, 0xeb, 0x56, 0xfe, 0xfb, 0xc8, 0x00,
- 0x5c, 0x91, 0xd0, 0xa5, 0x06, 0xdd, 0x3c, 0xcc, 0x53, 0x84, 0xd7, 0xe2, 0xb1, 0x31, 0x0b, 0xf9,
- 0x7d, 0x48, 0x0f, 0xea, 0x57, 0xbe, 0x58, 0x99, 0x68, 0x4f, 0x01, 0x68, 0x6a, 0x3b, 0x22, 0x50,
- 0x9b, 0x38, 0x0c, 0xea, 0xc7, 0xd2, 0xc1, 0x95, 0x80, 0x0c, 0xef, 0xde, 0xf3, 0xbe, 0x19, 0x33,
- 0x04, 0x1c, 0x91, 0x80, 0x27, 0x8d, 0xa8, 0xe7, 0x60, 0xa0, 0xb3, 0x4d, 0x38, 0x15, 0xeb, 0xf9,
- 0xb1, 0x5e, 0x23, 0xfe, 0xde, 0x90, 0xaf, 0xff, 0x8a, 0x08, 0x72, 0xbf, 0xa8, 0xc0, 0x79, 0x92,
- 0x25, 0x4f, 0x0a, 0x65, 0xf8, 0xf9, 0xe3, 0x92, 0x57, 0x45, 0x3e, 0xad, 0x2c, 0x30, 0xce, 0xee,
- 0x19, 0xda, 0x05, 0x70, 0x83, 0x6f, 0xba, 0x97, 0xb0, 0x14, 0xa9, 0x4c, 0x82, 0x9b, 0x59, 0xc2,
- 0xdf, 0x58, 0x22, 0x86, 0x7e, 0x42, 0x81, 0x69, 0x33, 0x85, 0xc3, 0x09, 0x8e, 0x59, 0x3b, 0x86,
- 0xb3, 0x85, 0x3b, 0xa0, 0xa4, 0x41, 0x70, 0x6a, 0x57, 0xd0, 0x4f, 0x65, 0x46, 0x10, 0xe6, 0x82,
- 0xc7, 0xda, 0x71, 0x7c, 0x83, 0x39, 0x82, 0x09, 0x7f, 0x46, 0x01, 0x54, 0x4f, 0xe8, 0xd6, 0xc2,
- 0xf7, 0xf0, 0x99, 0x23, 0xb7, 0x20, 0x70, 0x0f, 0xa2, 0x64, 0x39, 0x4e, 0xe9, 0x04, 0x5b, 0x67,
- 0x2f, 0x85, 0xe7, 0x8b, 0x17, 0xbe, 0xbd, 0xae, 0x73, 0xda, 0x71, 0xc2, 0xd7, 0x39, 0x0d, 0x82,
- 0x53, 0xbb, 0xa2, 0xfe, 0xe6, 0x08, 0x37, 0xf5, 0x32, 0x17, 0x8f, 0x97, 0x60, 0x70, 0x43, 0xd3,
- 0x6f, 0x8b, 0xeb, 0xd5, 0x9c, 0x4e, 0x47, 0x0b, 0x0c, 0x03, 0x37, 0xb2, 0xf0, 0xff, 0xb1, 0xc0,
- 0x8a, 0x5e, 0x80, 0xbe, 0xba, 0xe5, 0x3f, 0xa0, 0x7f, 0x4f, 0x0f, 0xd7, 0x07, 0x61, 0x18, 0x92,
- 0xf2, 0x6a, 0x0d, 0x53, 0xa4, 0xc8, 0x82, 0x61, 0x4b, 0x58, 0x46, 0x85, 0xf1, 0xea, 0xe9, 0xbc,
- 0x04, 0x02, 0x0b, 0x6b, 0x60, 0xd7, 0xf5, 0x4b, 0x70, 0x40, 0x83, 0xd2, 0x8b, 0x5d, 0x5f, 0xe6,
- 0xa6, 0x17, 0x5c, 0xf8, 0xc8, 0xf1, 0x59, 0xe3, 0x97, 0x3e, 0x04, 0x06, 0x3d, 0xcd, 0xb0, 0x3c,
- 0xff, 0x31, 0xfc, 0x13, 0x79, 0xa9, 0xad, 0x51, 0x2c, 0xa1, 0x01, 0x94, 0xfd, 0x74, 0xb1, 0x40,
- 0x8e, 0x36, 0x60, 0x90, 0x3f, 0x88, 0x17, 0x9f, 0x50, 0xee, 0xeb, 0x33, 0xfe, 0xc6, 0x9e, 0x6f,
- 0x03, 0xfe, 0x3f, 0x16, 0x98, 0xd1, 0xcb, 0x30, 0xec, 0xfa, 0xde, 0x66, 0xc3, 0xbd, 0x4d, 0x5d,
- 0xe0, 0x6a, 0x26, 0x9e, 0xf7, 0x0a, 0x1f, 0xb3, 0x00, 0x3f, 0xda, 0x80, 0x21, 0x43, 0x68, 0x4c,
- 0x23, 0xf9, 0xb7, 0x9d, 0xaf, 0x0d, 0x31, 0x6d, 0xc3, 0x57, 0x84, 0x7c, 0xc4, 0x59, 0x2e, 0x25,
- 0xf0, 0x75, 0x74, 0x29, 0x41, 0xaf, 0x00, 0x10, 0xdf, 0x42, 0xee, 0xce, 0x8c, 0xe6, 0xdf, 0x32,
- 0x92, 0x9d, 0xdd, 0x17, 0x88, 0x82, 0x22, 0x17, 0x4b, 0x44, 0xd0, 0xab, 0xb2, 0x49, 0x6e, 0xac,
- 0xb7, 0x18, 0x1f, 0xc9, 0xa8, 0x35, 0xe1, 0xcd, 0x5c, 0x60, 0x0d, 0x92, 0x2c, 0x65, 0xea, 0xef,
- 0x01, 0x40, 0x78, 0x6b, 0x8b, 0x36, 0x61, 0xd8, 0xa7, 0xd2, 0x4b, 0x94, 0x9d, 0xeb, 0x02, 0xcc,
- 0xb7, 0x97, 0xff, 0x0b, 0x07, 0xb8, 0x51, 0x29, 0x2d, 0xda, 0x53, 0x98, 0x00, 0xb7, 0xbb, 0x48,
- 0x4f, 0xaf, 0x00, 0xe8, 0x61, 0x0c, 0xd7, 0xbe, 0xfc, 0x6b, 0x15, 0xc4, 0x77, 0x0d, 0xd7, 0x4a,
- 0x0a, 0x01, 0x2b, 0x11, 0xc9, 0x70, 0x3a, 0xef, 0xcf, 0xe5, 0x74, 0xfe, 0x04, 0x9c, 0x12, 0x4e,
- 0x7e, 0x15, 0x76, 0x89, 0xe8, 0xed, 0x8a, 0x77, 0x99, 0xcc, 0xfd, 0xb3, 0x14, 0x05, 0xe1, 0x78,
- 0x5d, 0xf4, 0xaf, 0x14, 0x18, 0xd6, 0x85, 0x80, 0x26, 0x78, 0xdb, 0x72, 0x6f, 0x77, 0xf6, 0x73,
- 0xbe, 0xbc, 0xc7, 0x05, 0xf9, 0x67, 0x7d, 0xae, 0xea, 0x17, 0x1f, 0x91, 0x18, 0x1f, 0xf4, 0x1a,
- 0xfd, 0xae, 0x02, 0xa3, 0x9a, 0x69, 0xda, 0xba, 0xe6, 0xb1, 0xe8, 0x7f, 0xfc, 0xc1, 0xe8, 0xad,
- 0x1e, 0x47, 0x31, 0x1f, 0x62, 0xe4, 0x03, 0x79, 0x5f, 0x60, 0x09, 0x08, 0x21, 0x47, 0x34, 0x16,
- 0xb9, 0xfb, 0xe8, 0x1f, 0x2b, 0x70, 0x3f, 0x7f, 0xa5, 0x5b, 0xa2, 0x32, 0xd7, 0xa6, 0xa1, 0x6b,
- 0x1e, 0xe1, 0x21, 0x49, 0xfd, 0x17, 0x62, 0xdc, 0x45, 0x7e, 0xf8, 0xd0, 0x2e, 0xf2, 0x57, 0xf7,
- 0xf7, 0x8a, 0xf7, 0x97, 0xba, 0xc0, 0x8d, 0xbb, 0xea, 0x01, 0xba, 0x0b, 0xe3, 0xa6, 0x1c, 0x5e,
- 0x5c, 0x30, 0xf9, 0x5c, 0xb7, 0xab, 0x91, 0x38, 0xe5, 0xdc, 0xc0, 0x10, 0x29, 0xc2, 0x51, 0x52,
- 0xb3, 0xb7, 0x61, 0x3c, 0xb2, 0xd1, 0x8e, 0xd5, 0x2e, 0x6d, 0xc1, 0x64, 0x7c, 0x3f, 0x1c, 0xab,
- 0x9e, 0x77, 0x13, 0x46, 0x02, 0x61, 0x01, 0x5d, 0x92, 0x08, 0x85, 0xa2, 0xd7, 0x4d, 0xb2, 0xcb,
- 0xa9, 0x16, 0x23, 0x36, 0x14, 0x7e, 0x69, 0xca, 0x82, 0x33, 0x0a, 0x84, 0xea, 0x1f, 0x88, 0x4b,
- 0xd3, 0x35, 0xd2, 0x6c, 0x99, 0x9a, 0x47, 0xde, 0xf8, 0x6e, 0x46, 0xea, 0x7f, 0x54, 0xf8, 0x79,
- 0xc3, 0x45, 0x1b, 0xa4, 0xc1, 0x68, 0x93, 0xe7, 0xb6, 0x63, 0xa1, 0x1c, 0x95, 0xfc, 0x41, 0x24,
- 0x57, 0x42, 0x34, 0x58, 0xc6, 0x89, 0xee, 0xc0, 0x88, 0x2f, 0x0c, 0xfa, 0x96, 0x9a, 0xa5, 0xde,
- 0x84, 0xb3, 0x40, 0xee, 0x0c, 0x8e, 0x56, 0xbf, 0xc4, 0xc5, 0x21, 0x2d, 0x55, 0x03, 0x94, 0x6c,
- 0x83, 0x1e, 0x08, 0x9f, 0xab, 0x29, 0xd1, 0x6c, 0x34, 0x89, 0x27, 0x6b, 0xbe, 0x91, 0xb5, 0x90,
- 0x65, 0x64, 0x55, 0x7f, 0xa3, 0x00, 0xd3, 0x42, 0xf5, 0x9c, 0xd7, 0x75, 0xbb, 0x6d, 0x79, 0xe1,
- 0x2b, 0x62, 0xfe, 0x34, 0x5f, 0x10, 0x61, 0xe2, 0x24, 0x7f, 0xb7, 0x8f, 0x05, 0x04, 0xdd, 0xe2,
- 0xd6, 0x4f, 0xab, 0xbe, 0x66, 0xdf, 0x26, 0x56, 0xc8, 0x25, 0xe4, 0x18, 0x18, 0x8b, 0x69, 0x15,
- 0x70, 0x7a, 0x3b, 0xb4, 0x0d, 0xa8, 0xa9, 0xed, 0xc4, 0xb1, 0xe5, 0xcb, 0x71, 0xc6, 0xf4, 0xc5,
- 0x95, 0x04, 0x36, 0x9c, 0x42, 0x81, 0x1e, 0xa4, 0x54, 0x92, 0x6b, 0x79, 0xa4, 0xce, 0x87, 0xe8,
- 0xfb, 0x6c, 0xb0, 0x83, 0x74, 0x3e, 0x0a, 0xc2, 0xf1, 0xba, 0xea, 0xc7, 0x06, 0xe1, 0x7c, 0x74,
- 0x12, 0xe9, 0x17, 0xea, 0xbf, 0x9e, 0x7f, 0xca, 0x7f, 0x1a, 0xc6, 0x27, 0xf2, 0x81, 0xf8, 0xd3,
- 0xb0, 0x19, 0xd9, 0x27, 0x48, 0x34, 0x8a, 0x3c, 0x13, 0xfb, 0x3a, 0x3c, 0x85, 0xcf, 0x78, 0xfb,
- 0xdc, 0x77, 0xac, 0x4f, 0xfe, 0x3f, 0xa9, 0xc0, 0x6c, 0xb4, 0x78, 0xc9, 0xb0, 0x0c, 0x77, 0x4b,
- 0xa4, 0x35, 0x39, 0xfc, 0xcb, 0x34, 0x96, 0x18, 0x79, 0x39, 0x13, 0x23, 0xee, 0x40, 0x0d, 0x7d,
- 0x9f, 0x02, 0x17, 0x62, 0xf3, 0x12, 0x49, 0xb2, 0x72, 0xf8, 0x47, 0x6a, 0x2c, 0x76, 0xcb, 0x72,
- 0x36, 0x4a, 0xdc, 0x89, 0x5e, 0xa7, 0x80, 0x9e, 0x83, 0xaf, 0x97, 0x80, 0x9e, 0xbf, 0x50, 0x80,
- 0x01, 0xe6, 0x16, 0xf5, 0xc6, 0x78, 0x4f, 0xc4, 0xba, 0x9a, 0xe9, 0xce, 0xda, 0x88, 0xb9, 0xb3,
- 0x3e, 0x95, 0x9f, 0x44, 0x67, 0x7f, 0xd6, 0xf7, 0xc1, 0x59, 0x56, 0x6d, 0xbe, 0xce, 0x0c, 0x6d,
- 0x2e, 0xa9, 0xcf, 0xd7, 0xeb, 0x4c, 0xbd, 0x3d, 0xf8, 0x8e, 0xec, 0x12, 0xf4, 0xb5, 0x1d, 0x33,
- 0x1e, 0x21, 0x76, 0x1d, 0x2f, 0x63, 0x5a, 0xae, 0x7e, 0x52, 0x81, 0x49, 0x86, 0x5b, 0x62, 0x31,
- 0x68, 0x1b, 0x86, 0x1d, 0xc1, 0x66, 0xc4, 0xda, 0x2c, 0xe7, 0x1e, 0x5a, 0x0a, 0xeb, 0xe2, 0x1a,
- 0x9b, 0xff, 0x0b, 0x07, 0xb4, 0xd4, 0x3f, 0x1d, 0x80, 0x99, 0xac, 0x46, 0xe8, 0x87, 0x14, 0x38,
- 0xab, 0x87, 0x12, 0xe7, 0x7c, 0xdb, 0xdb, 0xb2, 0x1d, 0x3f, 0x61, 0x42, 0x6e, 0x73, 0x48, 0x69,
- 0x3e, 0xe8, 0x15, 0xcb, 0x12, 0x52, 0x4a, 0xa5, 0x80, 0x33, 0x28, 0xa3, 0x57, 0x01, 0x5c, 0x77,
- 0xeb, 0x26, 0xd9, 0x6d, 0x69, 0x86, 0xef, 0x98, 0x75, 0x33, 0xff, 0x36, 0xa8, 0xdd, 0x10, 0xa8,
- 0x82, 0x4e, 0x71, 0x5b, 0x75, 0x58, 0x2e, 0x91, 0x43, 0x1f, 0x55, 0x60, 0xdc, 0x96, 0xc3, 0xb1,
- 0xf4, 0xe2, 0xab, 0x9f, 0x1a, 0xd7, 0x85, 0x4b, 0xda, 0x51, 0x50, 0x94, 0x24, 0x5d, 0x96, 0x29,
- 0x37, 0x7e, 0xb2, 0x09, 0xde, 0xb7, 0x92, 0x4f, 0x06, 0xca, 0x38, 0x26, 0xb9, 0xd6, 0x9e, 0x04,
- 0x27, 0xc9, 0xb3, 0x4e, 0x11, 0x4f, 0xaf, 0x2f, 0x5a, 0xba, 0xb3, 0xcb, 0x02, 0x00, 0xd0, 0x4e,
- 0x0d, 0xe6, 0xef, 0xd4, 0xe2, 0x5a, 0xa9, 0x1c, 0x41, 0x16, 0xed, 0x54, 0x12, 0x9c, 0x24, 0xaf,
- 0x7e, 0xa4, 0x00, 0xe7, 0xd8, 0x32, 0xdf, 0x6c, 0x6f, 0x10, 0xee, 0x5b, 0xf5, 0x0f, 0x2e, 0x7e,
- 0xce, 0x6f, 0x2b, 0x30, 0xc2, 0xe6, 0xe0, 0x0d, 0xf2, 0x04, 0x93, 0xf5, 0x35, 0xc3, 0x7f, 0xf9,
- 0xb7, 0x14, 0x98, 0x4a, 0xa4, 0x88, 0xea, 0xea, 0x01, 0xdf, 0x89, 0xb9, 0xd6, 0xbe, 0x25, 0x4c,
- 0x4b, 0xd9, 0x17, 0xc6, 0xad, 0x88, 0xa7, 0xa4, 0x54, 0x9f, 0x83, 0xf1, 0x88, 0xfb, 0xb2, 0x14,
- 0xe1, 0x31, 0x2d, 0x36, 0xa5, 0x1c, 0xc0, 0xb1, 0xd0, 0x29, 0xf4, 0x64, 0xb8, 0xe5, 0x93, 0x9c,
- 0xed, 0x1f, 0xce, 0x96, 0x47, 0x62, 0xcb, 0xfb, 0xd7, 0x38, 0x2c, 0x6e, 0xa4, 0xdb, 0xcb, 0x35,
- 0x0e, 0x0b, 0x40, 0x29, 0xe2, 0xbc, 0xf2, 0xff, 0xb1, 0xc0, 0x8a, 0x9e, 0x8e, 0x46, 0x71, 0x5d,
- 0x0d, 0x75, 0xbb, 0xe9, 0x78, 0xec, 0x55, 0xb6, 0x25, 0x13, 0xb5, 0x11, 0xe6, 0x17, 0x41, 0xfc,
- 0x2c, 0xcb, 0x95, 0xbc, 0xa6, 0xbc, 0x5a, 0xe3, 0xe1, 0xfd, 0x82, 0x0b, 0xa0, 0xa8, 0xc5, 0xbb,
- 0xff, 0x24, 0x2c, 0xde, 0x0e, 0x8c, 0x6e, 0x19, 0x1b, 0xc4, 0xb1, 0xb8, 0x18, 0x33, 0x90, 0x5f,
- 0x42, 0xbb, 0x11, 0xa2, 0xe1, 0x66, 0x00, 0xa9, 0x00, 0xcb, 0x44, 0x90, 0x13, 0x89, 0x45, 0x3d,
- 0x98, 0x5f, 0x2a, 0x09, 0x4d, 0xd3, 0xe1, 0x38, 0x33, 0xe2, 0x50, 0x5b, 0x00, 0x56, 0x10, 0xa0,
- 0xb5, 0x97, 0x8b, 0xa1, 0x30, 0xcc, 0x2b, 0x17, 0x3a, 0xc2, 0xdf, 0x58, 0xa2, 0x40, 0xe7, 0xb5,
- 0x19, 0xe6, 0x2b, 0x10, 0x66, 0xc6, 0xa7, 0x7a, 0xcc, 0x19, 0x21, 0xcc, 0x2b, 0x61, 0x01, 0x96,
- 0x89, 0xd0, 0x31, 0x36, 0x83, 0x28, 0xfd, 0xc2, 0x8c, 0x98, 0x6b, 0x8c, 0x61, 0xac, 0x7f, 0x3e,
- 0xc6, 0xf0, 0x37, 0x96, 0x28, 0xa0, 0x97, 0xa5, 0xfb, 0x43, 0xc8, 0x6f, 0xa4, 0xea, 0xea, 0xee,
- 0xf0, 0x9d, 0xa1, 0xad, 0x66, 0x94, 0x7d, 0xa7, 0x17, 0x24, 0x3b, 0x0d, 0xcb, 0x5e, 0x40, 0x79,
- 0x47, 0xc2, 0x6e, 0x13, 0x3e, 0x9a, 0x18, 0xeb, 0xf8, 0x68, 0xa2, 0x44, 0xa5, 0x33, 0xe9, 0xe1,
- 0x21, 0x63, 0x08, 0xe3, 0xe1, 0x25, 0x48, 0x2d, 0x0e, 0xc4, 0xc9, 0xfa, 0x9c, 0xe1, 0x93, 0x3a,
- 0x6b, 0x3b, 0x21, 0x33, 0x7c, 0x5e, 0x86, 0x03, 0x28, 0xda, 0x86, 0x31, 0x57, 0x7a, 0x81, 0x31,
- 0x73, 0xaa, 0xd7, 0x2b, 0x44, 0xf1, 0xfa, 0x82, 0xb9, 0x3a, 0xca, 0x25, 0x38, 0x42, 0x27, 0x7a,
- 0xbf, 0x35, 0x79, 0xb2, 0xf7, 0x5b, 0xa8, 0x1d, 0x75, 0xae, 0x9e, 0x3a, 0x92, 0x30, 0x2d, 0x07,
- 0x3a, 0x5f, 0xd3, 0xa5, 0x25, 0x3b, 0x2d, 0xdb, 0x6d, 0x3b, 0x84, 0x65, 0xcb, 0x61, 0xcb, 0x83,
- 0xc2, 0xa5, 0x5d, 0x8c, 0x03, 0x71, 0xb2, 0x3e, 0xfa, 0x1e, 0x05, 0x26, 0xdd, 0x5d, 0xd7, 0x23,
- 0x4d, 0x7a, 0x6c, 0xd9, 0x16, 0xb1, 0x3c, 0x77, 0xe6, 0x74, 0xfe, 0xb0, 0xdf, 0xb5, 0x18, 0x2e,
- 0x7e, 0xec, 0xc4, 0x4b, 0x71, 0x82, 0x26, 0xdd, 0x39, 0x72, 0xa0, 0x97, 0x99, 0xe9, 0xfc, 0x3b,
- 0x47, 0x0e, 0x22, 0xc3, 0x77, 0x8e, 0x5c, 0x82, 0x23, 0x74, 0xd0, 0xa3, 0x30, 0xee, 0xfa, 0x29,
- 0xca, 0xd9, 0x0c, 0x9e, 0x09, 0x63, 0x71, 0xd6, 0x64, 0x00, 0x8e, 0xd6, 0x43, 0x1f, 0x82, 0x31,
- 0xf9, 0xec, 0x9c, 0x39, 0x7b, 0xd4, 0x51, 0xe9, 0x79, 0xcf, 0x65, 0x50, 0x84, 0x20, 0xc2, 0x70,
- 0x56, 0x7a, 0x1b, 0x28, 0x7f, 0xdf, 0xe7, 0xd8, 0x10, 0xb8, 0x3e, 0x9b, 0x5a, 0x03, 0x67, 0xb4,
- 0x44, 0x3f, 0x96, 0x7e, 0x5d, 0x3e, 0xc3, 0xb6, 0x74, 0xf5, 0x48, 0xae, 0xcb, 0x9f, 0x33, 0xbc,
- 0xad, 0x5b, 0x2d, 0x1e, 0x38, 0xec, 0x90, 0x37, 0xe7, 0xea, 0x1f, 0x29, 0x00, 0x81, 0xc1, 0xe4,
- 0x24, 0xae, 0x2a, 0xea, 0x11, 0x1b, 0xd2, 0x42, 0x4f, 0x06, 0x9e, 0xcc, 0xa4, 0x23, 0xea, 0x97,
- 0x15, 0x98, 0x08, 0xab, 0x9d, 0x80, 0x6a, 0xa4, 0x47, 0x55, 0xa3, 0x27, 0x7b, 0x1b, 0x57, 0x86,
- 0x7e, 0xf4, 0xbf, 0x0a, 0xf2, 0xa8, 0x98, 0xf4, 0xbb, 0x1d, 0xb9, 0xfa, 0xa7, 0xa4, 0x6f, 0xf4,
- 0x72, 0xf5, 0x2f, 0x07, 0xd7, 0x08, 0xc7, 0x9b, 0xe2, 0x0a, 0xf0, 0x9d, 0x11, 0xf9, 0xb3, 0x87,
- 0xb0, 0x36, 0x81, 0xb0, 0xe9, 0x93, 0xe6, 0x13, 0x70, 0x90, 0x30, 0xfa, 0x8a, 0x7c, 0x3c, 0xf5,
- 0x90, 0x28, 0x24, 0x32, 0xe0, 0xce, 0x4e, 0x17, 0xbf, 0x30, 0x05, 0xa3, 0x92, 0x6d, 0x31, 0xe6,
- 0xc8, 0xa0, 0x9c, 0x84, 0x23, 0x83, 0x07, 0xa3, 0x7a, 0x90, 0x29, 0xd2, 0x9f, 0xf6, 0x1e, 0x69,
- 0x06, 0xc7, 0x62, 0x98, 0x83, 0xd2, 0xc5, 0x32, 0x19, 0x2a, 0xbc, 0x05, 0x7b, 0xac, 0xef, 0x08,
- 0xdc, 0x4b, 0x3a, 0xed, 0xab, 0x47, 0x00, 0x7c, 0xf9, 0x9f, 0xd4, 0x45, 0x00, 0xf6, 0xc0, 0x75,
- 0xba, 0xe2, 0xde, 0x08, 0x60, 0x58, 0xaa, 0x97, 0xbc, 0x18, 0x1f, 0x38, 0xb1, 0x8b, 0x71, 0xba,
- 0x0d, 0x4c, 0x3f, 0xa7, 0x7e, 0x4f, 0xee, 0x6a, 0x41, 0x66, 0xfe, 0x70, 0x1b, 0x04, 0x45, 0x2e,
- 0x96, 0x88, 0x64, 0xf8, 0xb3, 0x0c, 0xe5, 0xf2, 0x67, 0x69, 0xc3, 0x69, 0x87, 0x78, 0xce, 0x6e,
- 0x69, 0x57, 0x67, 0x99, 0x4b, 0x1c, 0x8f, 0x69, 0xf0, 0xc3, 0xf9, 0xe2, 0x21, 0xe2, 0x24, 0x2a,
- 0x9c, 0x86, 0x3f, 0x22, 0x00, 0x8f, 0x74, 0x14, 0x80, 0xdf, 0x09, 0xa3, 0x1e, 0xd1, 0xb7, 0x2c,
- 0x43, 0xd7, 0xcc, 0x4a, 0x59, 0x84, 0xe7, 0x0e, 0x65, 0xb9, 0x10, 0x84, 0xe5, 0x7a, 0x68, 0x01,
- 0xfa, 0xda, 0x46, 0x5d, 0x68, 0x00, 0xdf, 0x12, 0x58, 0xe9, 0x2b, 0xe5, 0x7b, 0x7b, 0xc5, 0x37,
- 0x87, 0x0e, 0x22, 0xc1, 0xa8, 0xae, 0xb5, 0x6e, 0x37, 0xae, 0x79, 0xbb, 0x2d, 0xe2, 0xce, 0xad,
- 0x57, 0xca, 0x98, 0x36, 0x4e, 0xf3, 0xf5, 0x19, 0x3b, 0x84, 0xaf, 0xcf, 0x67, 0x14, 0x38, 0xad,
- 0xc5, 0x2f, 0x18, 0x88, 0x3b, 0x33, 0x9e, 0x9f, 0x5b, 0xa6, 0x5f, 0x5a, 0x2c, 0x5c, 0x10, 0xe3,
- 0x3b, 0x3d, 0x9f, 0x24, 0x87, 0xd3, 0xfa, 0x80, 0x1c, 0x40, 0x4d, 0xa3, 0x11, 0xa4, 0xb7, 0x17,
- 0xab, 0x3e, 0x91, 0xcf, 0x6e, 0xb3, 0x92, 0xc0, 0x84, 0x53, 0xb0, 0xa3, 0x3b, 0x30, 0x2a, 0x09,
- 0x49, 0x42, 0x93, 0x29, 0x1f, 0xc5, 0x3d, 0x08, 0xd7, 0x76, 0xe5, 0x3b, 0x0e, 0x99, 0x52, 0x70,
- 0xc9, 0x29, 0x99, 0x19, 0xc4, 0x45, 0x1f, 0x1b, 0xf5, 0x64, 0xfe, 0x4b, 0xce, 0x74, 0x8c, 0xb8,
- 0x03, 0x35, 0x16, 0x85, 0x90, 0x82, 0x25, 0xdd, 0x7c, 0x66, 0x2a, 0x7f, 0x18, 0x95, 0xe5, 0x28,
- 0x2a, 0xbe, 0x35, 0x63, 0x85, 0x38, 0x4e, 0x10, 0x2d, 0x01, 0x22, 0xdc, 0x94, 0x1e, 0x2a, 0x67,
- 0xee, 0x0c, 0x62, 0xf7, 0xef, 0x6c, 0x49, 0x17, 0x13, 0x50, 0x9c, 0xd2, 0x02, 0x79, 0x11, 0x5b,
- 0x49, 0x0f, 0x5a, 0x4e, 0x3c, 0x25, 0x4e, 0x47, 0x8b, 0xc9, 0x77, 0x2b, 0x89, 0x1c, 0xc9, 0x5c,
- 0xb9, 0xb9, 0xd1, 0x7b, 0x8e, 0x64, 0x41, 0xbe, 0x9b, 0x4c, 0xc9, 0x9f, 0x57, 0xe0, 0x5c, 0x33,
- 0x3d, 0x17, 0x24, 0xd3, 0x79, 0x72, 0x5e, 0x5c, 0x65, 0xa4, 0x97, 0x64, 0x66, 0x8c, 0xac, 0xdc,
- 0x93, 0x38, 0xab, 0x23, 0xea, 0x1f, 0x2a, 0xc2, 0x14, 0x7d, 0x82, 0xee, 0x48, 0xc7, 0x7d, 0x4f,
- 0xac, 0x3e, 0x07, 0x33, 0x35, 0x3f, 0x86, 0x68, 0x3d, 0x96, 0x2a, 0xe0, 0x3d, 0x30, 0xce, 0xaf,
- 0x82, 0x56, 0xb4, 0xd6, 0x6a, 0x78, 0x6f, 0x10, 0x44, 0x9b, 0x28, 0xc9, 0x40, 0x1c, 0xad, 0xab,
- 0x7e, 0x55, 0x81, 0x73, 0x51, 0xcc, 0xb6, 0x63, 0xdc, 0xed, 0x1d, 0x31, 0xfa, 0xb8, 0x02, 0xa3,
- 0xb7, 0x83, 0x5b, 0x2a, 0x5f, 0x74, 0xcb, 0xf5, 0x64, 0xc3, 0xef, 0x15, 0x71, 0xa4, 0x6b, 0xaf,
- 0x64, 0xfe, 0xc9, 0x10, 0xe8, 0x62, 0x99, 0xb4, 0xfa, 0x5f, 0x15, 0x48, 0x98, 0x0f, 0xd0, 0x06,
- 0x0c, 0x51, 0x22, 0xe5, 0xd5, 0x9a, 0xd8, 0x13, 0xef, 0xc9, 0x27, 0x55, 0x32, 0x14, 0xfc, 0x52,
- 0x44, 0xfc, 0xc0, 0x3e, 0x62, 0xb4, 0xcd, 0x9f, 0xf7, 0xfb, 0x79, 0x84, 0xc4, 0xf6, 0xc8, 0x25,
- 0xb6, 0xcb, 0xf9, 0x88, 0xb8, 0x5a, 0x2f, 0x97, 0xe0, 0x08, 0x1d, 0x75, 0x19, 0x20, 0x34, 0xf9,
- 0xf4, 0xec, 0xde, 0xf7, 0xef, 0x4e, 0xc3, 0x99, 0x9e, 0x1f, 0x23, 0x7e, 0x54, 0x81, 0xb3, 0x64,
- 0xdb, 0xd0, 0xbd, 0xf9, 0x4d, 0x8f, 0x38, 0xb7, 0x6e, 0xad, 0xac, 0x6d, 0x39, 0xc4, 0xdd, 0xb2,
- 0xcd, 0x7a, 0x37, 0xce, 0x8c, 0x29, 0x9e, 0x57, 0xcc, 0x34, 0xb1, 0x98, 0x8a, 0x11, 0x67, 0x50,
- 0x62, 0xe6, 0xae, 0x6d, 0x6e, 0x08, 0xc0, 0x54, 0xe7, 0x6a, 0x3b, 0xae, 0x27, 0xc2, 0x02, 0x72,
- 0x73, 0x57, 0x1c, 0x88, 0x93, 0xf5, 0xe3, 0x48, 0x58, 0x92, 0x3c, 0x26, 0xb7, 0x2b, 0x49, 0x24,
- 0x0c, 0x88, 0x93, 0xf5, 0x65, 0x24, 0x7c, 0xa5, 0xe8, 0xa1, 0x38, 0x90, 0x44, 0x12, 0x00, 0x71,
- 0xb2, 0x3e, 0xaa, 0xc3, 0x45, 0x87, 0xe8, 0x76, 0xb3, 0x49, 0xac, 0x3a, 0x9b, 0x94, 0x15, 0xcd,
- 0x69, 0x18, 0xd6, 0x92, 0xa3, 0xb1, 0x8a, 0xec, 0xf6, 0x40, 0x61, 0xf9, 0x6c, 0x2f, 0xe2, 0x0e,
- 0xf5, 0x70, 0x47, 0x2c, 0xa8, 0x09, 0xa7, 0xda, 0x8c, 0xff, 0x3b, 0x2c, 0x6c, 0xd8, 0xb6, 0x66,
- 0x8a, 0x2b, 0x82, 0xc3, 0xae, 0x18, 0x3b, 0xa8, 0xd7, 0xa3, 0xa8, 0x70, 0x1c, 0x37, 0xda, 0xa5,
- 0xe2, 0xb9, 0xe8, 0x8e, 0x44, 0x72, 0x38, 0x17, 0x49, 0x21, 0xa2, 0x27, 0xd0, 0xe1, 0x34, 0x1a,
- 0xa8, 0x02, 0xa7, 0x3d, 0xcd, 0x69, 0x10, 0xaf, 0x54, 0x5d, 0xaf, 0x12, 0x47, 0xa7, 0x3c, 0xd6,
- 0xe4, 0xd2, 0xba, 0xc2, 0x51, 0xad, 0x25, 0xc1, 0x38, 0xad, 0x0d, 0xfa, 0x10, 0xbc, 0x25, 0x3a,
- 0xa9, 0xcb, 0xf6, 0x1d, 0xe2, 0x2c, 0xd8, 0x6d, 0xab, 0x1e, 0x45, 0x0e, 0x0c, 0xf9, 0x03, 0xfb,
- 0x7b, 0xc5, 0xb7, 0xe0, 0x6e, 0x1a, 0xe0, 0xee, 0xf0, 0x26, 0x3b, 0xb0, 0xde, 0x6a, 0xa5, 0x76,
- 0x60, 0x34, 0xab, 0x03, 0x19, 0x0d, 0x70, 0x77, 0x78, 0x11, 0x86, 0xb3, 0x7c, 0x62, 0x78, 0xf6,
- 0x65, 0x89, 0xe2, 0x18, 0xa3, 0xc8, 0xbe, 0xdf, 0xb5, 0xd4, 0x1a, 0x38, 0xa3, 0x25, 0x3d, 0x53,
- 0xae, 0x66, 0x0d, 0x3f, 0x41, 0x66, 0x9c, 0x91, 0x79, 0xdb, 0xfe, 0x5e, 0xf1, 0x2a, 0xee, 0xb2,
- 0x0d, 0xee, 0x1a, 0x7b, 0x4a, 0x57, 0xc2, 0x89, 0x48, 0x74, 0x65, 0x22, 0xab, 0x2b, 0xd9, 0x6d,
- 0x70, 0xd7, 0xd8, 0xd1, 0xf7, 0x2a, 0x70, 0x5e, 0x6f, 0xb5, 0x6f, 0x18, 0xae, 0x67, 0x37, 0x1c,
- 0xad, 0x59, 0x26, 0xba, 0xb6, 0x7b, 0x43, 0x33, 0x37, 0x97, 0x8d, 0x4d, 0x22, 0x94, 0x8e, 0xc3,
- 0x7e, 0x38, 0xec, 0xe1, 0x6d, 0xa9, 0xba, 0x9e, 0x8e, 0x14, 0x67, 0xd3, 0x43, 0x3f, 0xac, 0xc0,
- 0xc5, 0x26, 0xeb, 0x62, 0x46, 0x87, 0x26, 0x73, 0x75, 0x88, 0x71, 0xb1, 0x95, 0x0e, 0x78, 0x71,
- 0x47, 0xaa, 0x6c, 0x92, 0x78, 0x85, 0xf9, 0x46, 0xc3, 0x21, 0x0d, 0x86, 0x35, 0xe0, 0x2e, 0x53,
- 0xf9, 0x27, 0x69, 0x25, 0x0b, 0x29, 0xce, 0xa6, 0x87, 0x5e, 0x86, 0xcb, 0x99, 0xc0, 0x92, 0xdd,
- 0xb6, 0x3c, 0x76, 0x09, 0xd3, 0xb7, 0xa0, 0xee, 0xef, 0x15, 0x2f, 0xaf, 0x74, 0xac, 0x89, 0x0f,
- 0xc0, 0xc4, 0x42, 0x8b, 0x44, 0xc2, 0x00, 0x9c, 0x66, 0x92, 0xd8, 0x8b, 0xb9, 0xb2, 0xed, 0x1e,
- 0xe1, 0xdb, 0xff, 0x2f, 0x47, 0xdf, 0xfe, 0x4f, 0xb3, 0x5e, 0xbd, 0xef, 0xe8, 0x7a, 0xf5, 0x8d,
- 0x07, 0xff, 0xdd, 0x3c, 0x04, 0xf9, 0x8c, 0x02, 0xe2, 0xfd, 0x26, 0xba, 0x18, 0x71, 0x3b, 0x1a,
- 0x8e, 0xb9, 0x1c, 0xf9, 0x49, 0x6f, 0x0b, 0xa9, 0x49, 0x6f, 0xdf, 0x2a, 0xc5, 0x58, 0x1e, 0x09,
- 0x95, 0x25, 0x8e, 0x39, 0x0c, 0xb2, 0x8c, 0x1e, 0x84, 0x91, 0x40, 0xa9, 0x16, 0xc6, 0x4e, 0x96,
- 0x70, 0x26, 0xd4, 0xbe, 0x43, 0xb8, 0xfa, 0xfb, 0x0a, 0x40, 0x98, 0xcb, 0x19, 0xdd, 0x07, 0x03,
- 0xba, 0xa9, 0xb9, 0xbe, 0x4b, 0x51, 0x70, 0x63, 0xc0, 0x6e, 0x22, 0x31, 0x87, 0x1d, 0xfc, 0x18,
- 0x01, 0xa9, 0x30, 0xd8, 0x66, 0xd9, 0x2b, 0xc5, 0x03, 0x02, 0xe6, 0x02, 0xb3, 0xce, 0x4a, 0xb0,
- 0x80, 0xa0, 0x75, 0x18, 0x6a, 0x1a, 0x16, 0x7b, 0xeb, 0xd1, 0x9f, 0xeb, 0xad, 0x07, 0xd3, 0x07,
- 0x56, 0x38, 0x0a, 0xec, 0xe3, 0x52, 0x7f, 0x51, 0x81, 0x53, 0xd1, 0xa0, 0xd7, 0x2c, 0xe4, 0x8d,
- 0x88, 0x85, 0x2a, 0x62, 0xed, 0xb3, 0xa6, 0x22, 0xc6, 0x23, 0xf6, 0x61, 0xd1, 0xdb, 0xe9, 0x1e,
- 0x6e, 0x1f, 0xd2, 0x63, 0x6f, 0x1f, 0x70, 0x11, 0xf0, 0xa3, 0xa7, 0x61, 0x90, 0x2b, 0xda, 0x54,
- 0x8e, 0x4f, 0x89, 0x6d, 0x75, 0x33, 0x7f, 0x3a, 0x89, 0x3c, 0x11, 0x71, 0xe4, 0xa4, 0x9a, 0x85,
- 0x8e, 0x49, 0x35, 0x31, 0xf4, 0xe9, 0x8e, 0xd1, 0x8b, 0x27, 0x52, 0x09, 0x57, 0xb8, 0x27, 0x52,
- 0x09, 0x57, 0x30, 0x45, 0x86, 0xbc, 0x88, 0x8b, 0x4e, 0x7f, 0x7e, 0x13, 0x10, 0x9f, 0x00, 0xc9,
- 0x51, 0x67, 0xa2, 0xa3, 0x93, 0x8e, 0x1f, 0x48, 0x7f, 0x20, 0xff, 0xe3, 0x20, 0x31, 0xe5, 0xdd,
- 0x04, 0xd2, 0xf7, 0x3f, 0xa4, 0xc1, 0xcc, 0x0f, 0x69, 0x13, 0x86, 0xc4, 0xa7, 0x20, 0x14, 0x82,
- 0xf7, 0xf4, 0x90, 0x3a, 0x5e, 0x4a, 0x52, 0xc5, 0x0b, 0xb0, 0x8f, 0x9c, 0x6a, 0x99, 0x4d, 0x6d,
- 0xc7, 0x68, 0xb6, 0x9b, 0x4c, 0x0b, 0x18, 0x90, 0xab, 0xb2, 0x62, 0xec, 0xc3, 0x59, 0x55, 0xfe,
- 0xa6, 0x8a, 0x49, 0xed, 0x72, 0x55, 0x5e, 0x8c, 0x7d, 0x38, 0x7a, 0x01, 0x86, 0x9b, 0xda, 0x4e,
- 0xad, 0xed, 0x34, 0x88, 0x70, 0xd0, 0xc9, 0x36, 0x0a, 0xb5, 0x3d, 0xc3, 0x9c, 0x33, 0x2c, 0xcf,
- 0xf5, 0x9c, 0xb9, 0x8a, 0xe5, 0xdd, 0x72, 0x6a, 0x1e, 0x73, 0x00, 0x62, 0xbb, 0x6e, 0x45, 0x60,
- 0xc1, 0x01, 0x3e, 0x64, 0xc2, 0x44, 0x53, 0xdb, 0x59, 0xb7, 0x34, 0x9e, 0x23, 0x41, 0x48, 0xd9,
- 0x79, 0x28, 0x30, 0xab, 0xdc, 0x4a, 0x04, 0x17, 0x8e, 0xe1, 0x4e, 0x71, 0x06, 0x1d, 0x3b, 0x2e,
- 0x67, 0xd0, 0xf9, 0x20, 0x4a, 0x01, 0x37, 0xe9, 0x9f, 0x4f, 0x0d, 0xff, 0xd7, 0x31, 0x02, 0xc1,
- 0x4b, 0x41, 0x04, 0x82, 0x89, 0xfc, 0xde, 0x8b, 0x1d, 0xa2, 0x0f, 0xb4, 0x61, 0xb4, 0xae, 0x79,
- 0x1a, 0x2f, 0x75, 0x67, 0x4e, 0xe5, 0xbf, 0x9d, 0x2e, 0x07, 0x68, 0x42, 0x96, 0x14, 0x96, 0xb9,
- 0x58, 0xa6, 0x83, 0x6e, 0xc1, 0x19, 0xfa, 0xb1, 0x9a, 0xc4, 0x0b, 0xab, 0x30, 0x9b, 0xd9, 0x24,
- 0xfb, 0x7e, 0xd8, 0x2b, 0xb5, 0x9b, 0x69, 0x15, 0x70, 0x7a, 0xbb, 0x30, 0x54, 0xed, 0x54, 0x7a,
- 0xa8, 0x5a, 0xf4, 0xa9, 0x34, 0xb7, 0x1b, 0xc4, 0xe6, 0xf4, 0xbd, 0xf9, 0x79, 0x43, 0x6e, 0xe7,
- 0x9b, 0x7f, 0xa1, 0xc0, 0x8c, 0xd8, 0x65, 0xc2, 0x55, 0xc6, 0x24, 0xce, 0x8a, 0x66, 0x69, 0x0d,
- 0xe2, 0x08, 0x3b, 0xf9, 0x5a, 0x0f, 0xfc, 0x21, 0x81, 0x33, 0x08, 0x0d, 0x71, 0xff, 0xfe, 0x5e,
- 0xf1, 0xca, 0x41, 0xb5, 0x70, 0x66, 0xdf, 0x90, 0x03, 0x43, 0xee, 0xae, 0xab, 0x7b, 0xa6, 0x2b,
- 0x64, 0xd0, 0xeb, 0x3d, 0x70, 0xd6, 0x1a, 0xc7, 0xc4, 0x59, 0x6b, 0x98, 0x1a, 0x91, 0x97, 0x62,
- 0x9f, 0x10, 0xfa, 0x41, 0x05, 0xa6, 0xc4, 0xe5, 0x99, 0x14, 0x7a, 0xe7, 0x4c, 0xfe, 0x77, 0x32,
- 0xa5, 0x38, 0x32, 0xdf, 0x3d, 0x86, 0x59, 0x93, 0x12, 0x50, 0x9c, 0xa4, 0x4e, 0x0f, 0xd5, 0x96,
- 0x63, 0xd8, 0x8e, 0xe1, 0xed, 0x32, 0x47, 0xa4, 0x01, 0x3f, 0x40, 0x3d, 0x2f, 0xc3, 0x01, 0x14,
- 0xd5, 0x60, 0x82, 0x5b, 0x6d, 0x6a, 0x9e, 0xa3, 0x79, 0xa4, 0xb1, 0x2b, 0xbc, 0x85, 0x1e, 0x64,
- 0x29, 0x84, 0x23, 0x90, 0x7b, 0x7b, 0xc5, 0x33, 0x62, 0x6d, 0xa2, 0x00, 0x1c, 0x43, 0x81, 0x3e,
- 0x10, 0x73, 0xde, 0x9a, 0xc9, 0x9f, 0x5e, 0x90, 0xaf, 0xc5, 0x61, 0x5c, 0xb8, 0x7a, 0x8d, 0x26,
- 0xd7, 0x43, 0x8a, 0x97, 0xd9, 0xc7, 0x61, 0x4c, 0xde, 0x35, 0x87, 0x0a, 0x62, 0xe7, 0x01, 0x4a,
- 0x0e, 0xf6, 0xb8, 0xe3, 0xfc, 0xa8, 0x3f, 0xa9, 0xc0, 0x64, 0x5c, 0x76, 0x41, 0x5b, 0x30, 0x24,
- 0x18, 0x99, 0xa0, 0x3a, 0x9f, 0xd7, 0x6b, 0xd9, 0x24, 0xe2, 0x79, 0x30, 0x17, 0x85, 0x45, 0x11,
- 0xf6, 0xd1, 0xcb, 0x2f, 0x12, 0x0a, 0x1d, 0x5e, 0x24, 0x3c, 0x01, 0x67, 0xd3, 0x59, 0x1a, 0x55,
- 0x24, 0x34, 0xaa, 0x5f, 0x09, 0xa3, 0x75, 0xa0, 0x48, 0x30, 0xa5, 0x0b, 0x73, 0x98, 0xfa, 0x41,
- 0x88, 0xa7, 0x36, 0x43, 0x2f, 0xc3, 0x88, 0xeb, 0x6e, 0x71, 0x3f, 0x33, 0x31, 0xc8, 0x7c, 0x57,
- 0x3d, 0x7e, 0x9a, 0x19, 0xae, 0xfb, 0x04, 0x3f, 0x71, 0x88, 0x7e, 0xe1, 0xf9, 0x2f, 0x7d, 0xf5,
- 0xf2, 0x9b, 0xfe, 0xe0, 0xab, 0x97, 0xdf, 0xf4, 0x95, 0xaf, 0x5e, 0x7e, 0xd3, 0x87, 0xf7, 0x2f,
- 0x2b, 0x5f, 0xda, 0xbf, 0xac, 0xfc, 0xc1, 0xfe, 0x65, 0xe5, 0x2b, 0xfb, 0x97, 0x95, 0xbf, 0xdc,
- 0xbf, 0xac, 0xfc, 0xc0, 0xbf, 0xbf, 0xfc, 0xa6, 0x17, 0x1e, 0x0e, 0xa9, 0x5f, 0xf3, 0x89, 0x86,
- 0xff, 0xb4, 0x6e, 0x37, 0xa8, 0xd2, 0xea, 0xfa, 0x5a, 0x2b, 0xa3, 0xfe, 0x7f, 0x02, 0x00, 0x00,
- 0xff, 0xff, 0x03, 0x88, 0x36, 0xbe, 0x42, 0x25, 0x01, 0x00,
+ 0x6d, 0x26, 0xc2, 0xd6, 0x63, 0xdb, 0x24, 0x98, 0x41, 0xe8, 0x3d, 0x8f, 0xfe, 0xf5, 0xef, 0x70,
+ 0xec, 0x9e, 0x47, 0xc1, 0x2e, 0xe6, 0xe5, 0xea, 0x17, 0x07, 0x82, 0xc9, 0x66, 0x97, 0xfa, 0x1b,
+ 0x30, 0xa2, 0x3b, 0x44, 0xf3, 0x48, 0x7d, 0x61, 0xb7, 0x9b, 0xce, 0x31, 0x39, 0xa0, 0xe4, 0xb7,
+ 0xc0, 0x61, 0x63, 0x7a, 0xe4, 0xca, 0x06, 0x9e, 0x85, 0x50, 0x3a, 0xc9, 0x34, 0xee, 0xfc, 0x76,
+ 0x18, 0xb0, 0xef, 0x58, 0x81, 0x73, 0x48, 0x47, 0xc2, 0x6c, 0x28, 0xb7, 0x68, 0x6d, 0xcc, 0x1b,
+ 0xc9, 0x69, 0x1b, 0xfa, 0x3b, 0xa4, 0x6d, 0x30, 0x61, 0xa8, 0xc9, 0x96, 0xa1, 0xa7, 0xc4, 0xb8,
+ 0x91, 0x05, 0x0d, 0x97, 0x88, 0xff, 0x76, 0xb1, 0x4f, 0x82, 0x8a, 0x4e, 0x96, 0xaf, 0xd1, 0x91,
+ 0x45, 0xa7, 0x40, 0xcd, 0x83, 0x43, 0x38, 0xda, 0x8d, 0xe6, 0x03, 0x19, 0xca, 0xaf, 0x27, 0x15,
+ 0xdd, 0x93, 0x52, 0x80, 0xf0, 0xa9, 0xcf, 0xca, 0x09, 0x82, 0xbe, 0xa0, 0xc0, 0xb9, 0x7a, 0x7a,
+ 0xc2, 0x35, 0xf1, 0x54, 0x9e, 0xcb, 0x31, 0x3b, 0x23, 0x87, 0xdb, 0x42, 0x51, 0x4c, 0x58, 0x56,
+ 0x92, 0x37, 0x9c, 0xd5, 0x19, 0xf5, 0xfb, 0xfb, 0x83, 0xaf, 0x49, 0x68, 0x3a, 0xd2, 0xf5, 0x50,
+ 0x4a, 0x1e, 0x3d, 0x14, 0x7a, 0x87, 0x9f, 0xfe, 0x8b, 0x6f, 0xd7, 0x4b, 0xf1, 0xf4, 0x5f, 0x63,
+ 0x82, 0x74, 0x24, 0xe5, 0x57, 0x1b, 0x4e, 0xbb, 0x9e, 0x66, 0x92, 0x9a, 0x21, 0x1e, 0x07, 0x5d,
+ 0x4f, 0x6b, 0xb6, 0x72, 0xe4, 0xdf, 0xe2, 0x81, 0x1a, 0x92, 0xa8, 0x70, 0x1a, 0x7e, 0xf4, 0xbd,
+ 0x2c, 0xf8, 0x9e, 0x66, 0xb2, 0xc7, 0x53, 0x9e, 0x83, 0x34, 0x24, 0x7e, 0x78, 0x73, 0x77, 0x11,
+ 0x5a, 0x2f, 0x1d, 0x1f, 0xce, 0xa4, 0x84, 0x5e, 0x85, 0x33, 0xf4, 0x00, 0x9c, 0xd7, 0x3d, 0x63,
+ 0xdb, 0xf0, 0x76, 0xc3, 0x2e, 0x1c, 0x3e, 0xe9, 0x16, 0xbb, 0x6d, 0x2f, 0xa7, 0x21, 0xc3, 0xe9,
+ 0x34, 0xd4, 0xbf, 0x51, 0x00, 0x25, 0xf7, 0x3a, 0x32, 0x61, 0xb8, 0xee, 0x47, 0x4e, 0x50, 0x8e,
+ 0x24, 0xab, 0x4e, 0x70, 0x84, 0x04, 0x01, 0x17, 0x02, 0x0a, 0xc8, 0x86, 0x91, 0x3b, 0x5b, 0x86,
+ 0x47, 0x4c, 0xc3, 0xf5, 0x8e, 0x28, 0x89, 0x4f, 0x10, 0x13, 0xfe, 0x39, 0x1f, 0x31, 0x0e, 0x69,
+ 0xa8, 0x9f, 0xea, 0x87, 0xe1, 0x20, 0x99, 0xe6, 0xc1, 0x66, 0xd6, 0x6d, 0x40, 0xba, 0x14, 0x10,
+ 0xb0, 0x17, 0x9d, 0x29, 0x93, 0x81, 0x4a, 0x09, 0x64, 0x38, 0x85, 0x00, 0x7a, 0x15, 0xa6, 0x0d,
+ 0x6b, 0xd3, 0xd1, 0x82, 0x70, 0x87, 0x25, 0x5f, 0x51, 0x96, 0x83, 0x30, 0xbb, 0x45, 0x57, 0x52,
+ 0xd0, 0xe1, 0x54, 0x22, 0x88, 0xc0, 0x10, 0xcf, 0x67, 0xec, 0xbf, 0xba, 0xe4, 0xd2, 0xd5, 0x73,
+ 0x59, 0x33, 0x64, 0xef, 0xbe, 0xec, 0xe9, 0xe3, 0xe6, 0xc1, 0x69, 0xf9, 0xff, 0xfe, 0x83, 0x94,
+ 0xd8, 0xf7, 0xa5, 0xfc, 0xf4, 0xc2, 0xb7, 0x2d, 0x1e, 0x9c, 0x36, 0x5a, 0x88, 0xe3, 0x04, 0xd5,
+ 0xdf, 0x55, 0x60, 0x80, 0xc7, 0x00, 0x3b, 0x7e, 0x51, 0xf3, 0xfd, 0x11, 0x51, 0xf3, 0x89, 0x3c,
+ 0x83, 0x64, 0x5d, 0xcd, 0xcc, 0xc8, 0xff, 0x3b, 0x0a, 0x8c, 0xb0, 0x1a, 0x27, 0x20, 0xfb, 0xbd,
+ 0x14, 0x95, 0xfd, 0x1e, 0xcb, 0x3d, 0x9a, 0x0c, 0xc9, 0xef, 0x77, 0xfb, 0xc4, 0x58, 0x98, 0x68,
+ 0x55, 0x81, 0xd3, 0xc2, 0x31, 0x76, 0xd9, 0xd8, 0x24, 0x74, 0x8b, 0x97, 0xb5, 0x5d, 0x57, 0xb8,
+ 0x6a, 0xf0, 0xa0, 0x33, 0x49, 0x30, 0x4e, 0x6b, 0x83, 0x7e, 0x55, 0xa1, 0x42, 0x8c, 0xe7, 0x18,
+ 0x7a, 0x4f, 0x8f, 0xc1, 0x41, 0xdf, 0xe6, 0x56, 0x38, 0x32, 0x7e, 0x37, 0x5d, 0x0f, 0xa5, 0x19,
+ 0x56, 0x7a, 0x6f, 0xaf, 0x58, 0x4c, 0xd1, 0x19, 0x87, 0x59, 0xa9, 0x5d, 0xef, 0xa3, 0x7f, 0xd1,
+ 0xb1, 0x0a, 0xbb, 0x8d, 0xf9, 0x3d, 0x46, 0x37, 0x60, 0xc0, 0xd5, 0xed, 0x96, 0xef, 0x5a, 0x7d,
+ 0x5f, 0x9a, 0x6e, 0x30, 0xae, 0x16, 0x0c, 0x26, 0xb8, 0x46, 0x5b, 0x62, 0x8e, 0x60, 0xf6, 0x65,
+ 0x18, 0x93, 0x7b, 0x9e, 0x72, 0xf7, 0x2d, 0x47, 0x2d, 0xe6, 0x0e, 0x69, 0x1c, 0x26, 0xdf, 0x95,
+ 0xff, 0xa8, 0x0f, 0x06, 0x31, 0x69, 0x88, 0x94, 0x69, 0x07, 0xdc, 0x39, 0x0d, 0x3f, 0xfd, 0x6f,
+ 0x21, 0xbf, 0x1f, 0x9e, 0x9c, 0x14, 0xe7, 0x05, 0xdb, 0x92, 0xe6, 0x40, 0xce, 0x00, 0x8c, 0xac,
+ 0x20, 0x91, 0x54, 0x5f, 0x7e, 0x83, 0x5a, 0x3e, 0xb0, 0x6e, 0x52, 0x47, 0xa1, 0x1f, 0x56, 0x00,
+ 0x69, 0xba, 0x4e, 0x5c, 0x17, 0x13, 0x97, 0xce, 0x3d, 0x17, 0x56, 0x39, 0x97, 0xcd, 0x17, 0x15,
+ 0x3b, 0x8e, 0x2d, 0x14, 0xdb, 0x12, 0x20, 0x17, 0xa7, 0x10, 0xef, 0x25, 0x9d, 0xd5, 0xef, 0x2b,
+ 0x30, 0x16, 0xc9, 0x16, 0xd6, 0x0c, 0x75, 0xe9, 0xf9, 0x4d, 0x76, 0x7c, 0xef, 0xaf, 0x0b, 0x1d,
+ 0x2a, 0x71, 0xfd, 0xfc, 0xad, 0x20, 0xdd, 0xc5, 0xd1, 0x24, 0x16, 0x53, 0x3f, 0xad, 0xc0, 0x59,
+ 0x7f, 0x40, 0xd1, 0xb8, 0xe6, 0xe8, 0x2a, 0x0c, 0x6b, 0x2d, 0x83, 0x29, 0x7a, 0x65, 0x55, 0xf9,
+ 0x7c, 0xb5, 0xc2, 0xca, 0x70, 0x00, 0x8d, 0xe4, 0x58, 0x2e, 0x1c, 0x98, 0x63, 0xf9, 0x2d, 0x52,
+ 0xd6, 0xe8, 0x81, 0x50, 0x76, 0x09, 0x08, 0x73, 0x63, 0x4e, 0xf5, 0x5d, 0x30, 0x52, 0xab, 0xdd,
+ 0xe0, 0x4b, 0x7a, 0x88, 0x17, 0x1f, 0xf5, 0x13, 0x7d, 0x30, 0x2e, 0x12, 0x34, 0x18, 0x4c, 0x05,
+ 0x74, 0x02, 0xe7, 0xdc, 0x1a, 0x8c, 0xb8, 0xc1, 0x1b, 0x46, 0x21, 0x9b, 0x4f, 0x05, 0xcf, 0x12,
+ 0xf1, 0x2c, 0x7b, 0xe1, 0xf3, 0x45, 0x88, 0x08, 0xdd, 0x84, 0xc1, 0x57, 0x28, 0xcf, 0xf5, 0xbf,
+ 0xd5, 0xae, 0x58, 0x5f, 0xf0, 0x21, 0x32, 0x76, 0xed, 0x62, 0x81, 0x02, 0xb9, 0xcc, 0x3d, 0x91,
+ 0x09, 0x81, 0xbd, 0x84, 0xea, 0x8c, 0xcc, 0x6c, 0x90, 0x33, 0x7e, 0x4c, 0x78, 0x39, 0xb2, 0x5f,
+ 0x38, 0x20, 0xc4, 0x52, 0x84, 0x46, 0x5a, 0xbc, 0x41, 0x52, 0x84, 0x46, 0xfa, 0x9c, 0x71, 0x5c,
+ 0x3f, 0x06, 0x67, 0x52, 0x27, 0xe3, 0x60, 0x11, 0x5b, 0xfd, 0x67, 0x05, 0xe8, 0xaf, 0x11, 0x52,
+ 0x3f, 0x81, 0x9d, 0xf9, 0x52, 0x44, 0x02, 0xfb, 0xf6, 0xdc, 0x49, 0x4a, 0xb3, 0x34, 0x7d, 0x9b,
+ 0x31, 0x4d, 0xdf, 0x93, 0xb9, 0x29, 0x74, 0x56, 0xf3, 0xfd, 0x55, 0x01, 0x86, 0x68, 0xb5, 0xf2,
+ 0x6a, 0x0d, 0x35, 0xa5, 0xad, 0x5c, 0xc8, 0x2f, 0x3e, 0x0b, 0x74, 0x07, 0x6d, 0x62, 0xfa, 0xe5,
+ 0x18, 0x22, 0xf1, 0x8b, 0x18, 0x64, 0xe5, 0x08, 0xc8, 0x89, 0xd8, 0x13, 0x8c, 0xa8, 0x9f, 0x57,
+ 0x06, 0x07, 0x84, 0xd0, 0x1d, 0xe9, 0x4e, 0xda, 0x9f, 0xdf, 0x76, 0x37, 0x9d, 0x68, 0x87, 0xeb,
+ 0xa9, 0xfa, 0x09, 0x05, 0x4e, 0xc5, 0x5a, 0x75, 0x71, 0x69, 0x3c, 0x16, 0x06, 0xa8, 0x7e, 0x5d,
+ 0xa1, 0xdf, 0x58, 0xca, 0x08, 0xba, 0xe8, 0x51, 0x98, 0x00, 0xac, 0xd0, 0x31, 0x01, 0xd8, 0x45,
+ 0xe8, 0xa7, 0x92, 0x91, 0x6c, 0xb3, 0x43, 0x05, 0x26, 0xcc, 0x4a, 0x91, 0x0e, 0x13, 0xba, 0x94,
+ 0xc2, 0x9d, 0x6c, 0x0a, 0xde, 0xd9, 0x15, 0x2b, 0x0e, 0x9e, 0x1b, 0x4b, 0x11, 0x14, 0x38, 0x86,
+ 0x52, 0xfd, 0x6d, 0x05, 0x86, 0xe9, 0x30, 0x4f, 0x80, 0x39, 0x7e, 0x67, 0x94, 0x39, 0xbe, 0x3b,
+ 0xef, 0x9e, 0xca, 0xe0, 0x89, 0x7f, 0x5d, 0x00, 0x96, 0xc1, 0x58, 0xd8, 0x17, 0x49, 0x96, 0x43,
+ 0x4a, 0x86, 0xcd, 0xd3, 0x15, 0x61, 0x78, 0x14, 0x53, 0x4a, 0x4b, 0xc6, 0x47, 0x6f, 0x8b, 0xd8,
+ 0x16, 0x45, 0x84, 0x8b, 0x14, 0xfb, 0xa2, 0xbb, 0x30, 0xee, 0x6e, 0xd9, 0xb6, 0x57, 0x0e, 0x3f,
+ 0x9e, 0xdc, 0x0f, 0x10, 0xcc, 0x59, 0xdc, 0x1f, 0x0a, 0x7f, 0xca, 0xad, 0xc9, 0xb8, 0x71, 0x94,
+ 0x14, 0x9a, 0x03, 0xd8, 0x30, 0x6d, 0xfd, 0x36, 0x37, 0x6d, 0xe2, 0xce, 0xc1, 0xcc, 0x78, 0x62,
+ 0x21, 0x28, 0xc5, 0x52, 0x8d, 0x9e, 0xac, 0xb8, 0xbe, 0xae, 0xf0, 0x99, 0x3e, 0xc4, 0x37, 0x7a,
+ 0x82, 0x86, 0x70, 0x6f, 0x85, 0x41, 0x87, 0xdd, 0x11, 0xc4, 0x8a, 0x05, 0x1f, 0x1f, 0xbf, 0x39,
+ 0x60, 0x01, 0xa5, 0xdb, 0x83, 0x5f, 0x7c, 0xfa, 0xc3, 0x07, 0x07, 0xf9, 0xba, 0xa2, 0xfe, 0xb2,
+ 0x18, 0x66, 0x90, 0x04, 0xbb, 0x05, 0xe3, 0xec, 0x66, 0x11, 0xcb, 0xbe, 0xfd, 0x8e, 0x2e, 0xbf,
+ 0x11, 0xb9, 0x69, 0x68, 0x96, 0x1b, 0x29, 0xc6, 0x51, 0x02, 0xe8, 0x51, 0x18, 0xf7, 0x47, 0xc7,
+ 0xad, 0x63, 0x0b, 0xa1, 0x87, 0x66, 0x55, 0x06, 0xe0, 0x68, 0x3d, 0xf5, 0x33, 0x05, 0xb8, 0xc4,
+ 0xfb, 0xce, 0x34, 0x2f, 0x65, 0xd2, 0x22, 0x56, 0x9d, 0x58, 0xfa, 0x2e, 0x93, 0xb3, 0xeb, 0x76,
+ 0x03, 0xbd, 0x0a, 0x83, 0x77, 0x08, 0xa9, 0x07, 0x4f, 0x18, 0xcf, 0xe5, 0xcf, 0x21, 0x9e, 0x41,
+ 0xe2, 0x39, 0x86, 0x9e, 0xbf, 0x06, 0xf3, 0xff, 0xb1, 0x20, 0x49, 0x89, 0xb7, 0x1c, 0x7b, 0x23,
+ 0x10, 0x07, 0x8f, 0x9e, 0x78, 0x95, 0xa1, 0xe7, 0xc4, 0xf9, 0xff, 0x58, 0x90, 0x54, 0xab, 0x70,
+ 0x5f, 0x17, 0x4d, 0x0f, 0x23, 0xf6, 0x1f, 0x84, 0x91, 0x8f, 0xfe, 0x30, 0x18, 0xff, 0x44, 0x81,
+ 0xfb, 0x25, 0x94, 0x8b, 0x3b, 0xf4, 0x26, 0x52, 0xd2, 0x5a, 0x9a, 0x4e, 0xef, 0xfa, 0x2c, 0x46,
+ 0xdd, 0xa1, 0xb2, 0xf6, 0x7e, 0x42, 0x81, 0x21, 0x6e, 0x91, 0xe7, 0xb3, 0xdf, 0x97, 0x7a, 0x9c,
+ 0xf2, 0xcc, 0x2e, 0xf9, 0xd9, 0xcc, 0xfc, 0xb1, 0xf1, 0xdf, 0x2e, 0xf6, 0xe9, 0xab, 0xff, 0x6a,
+ 0x00, 0xbe, 0xb5, 0x7b, 0x44, 0xe8, 0xeb, 0x8a, 0x9c, 0x6d, 0x9c, 0xeb, 0xc8, 0x9b, 0xc7, 0xdb,
+ 0xf9, 0x40, 0x1b, 0x24, 0x14, 0x0c, 0xcf, 0x25, 0x12, 0x92, 0x1f, 0x91, 0xa2, 0x29, 0x1c, 0x18,
+ 0xfa, 0xc7, 0x0a, 0x8c, 0xd1, 0x63, 0x29, 0x60, 0x2e, 0x7c, 0x99, 0x5a, 0xc7, 0x3c, 0xd2, 0x55,
+ 0x89, 0x64, 0x2c, 0xae, 0x95, 0x0c, 0xc2, 0x91, 0xbe, 0xa1, 0xf5, 0xe8, 0xf3, 0x1f, 0xbf, 0x22,
+ 0x5e, 0x4e, 0x93, 0x4b, 0x0e, 0x93, 0xee, 0x7f, 0xd6, 0x84, 0x89, 0xe8, 0xcc, 0x1f, 0xa7, 0x9a,
+ 0x6c, 0xf6, 0x29, 0x98, 0x4a, 0x8c, 0xfe, 0x50, 0x0a, 0x99, 0x2f, 0x0f, 0x42, 0x51, 0x9a, 0xea,
+ 0xb4, 0xf0, 0x34, 0xe8, 0x73, 0x0a, 0x8c, 0x6a, 0x96, 0x25, 0x0c, 0x9b, 0xfc, 0xfd, 0x5b, 0xef,
+ 0x71, 0x55, 0xd3, 0x48, 0xcd, 0xcd, 0x87, 0x64, 0x62, 0x96, 0x3b, 0x12, 0x04, 0xcb, 0xbd, 0xe9,
+ 0x60, 0x9d, 0x5b, 0x38, 0x31, 0xeb, 0x5c, 0xf4, 0x41, 0xff, 0x20, 0xee, 0xcb, 0x1f, 0xa8, 0xe2,
+ 0x80, 0xb9, 0x61, 0xe7, 0x7a, 0x86, 0x56, 0xf2, 0x07, 0x15, 0x76, 0xc8, 0x86, 0x51, 0x84, 0xc4,
+ 0x99, 0x94, 0xcb, 0xc8, 0xf2, 0xc0, 0x10, 0x45, 0xc1, 0xd9, 0x1d, 0x16, 0xe1, 0x28, 0x79, 0xf4,
+ 0x63, 0x0a, 0x8c, 0xdd, 0xb5, 0x2d, 0xcd, 0x14, 0x76, 0xd6, 0xe2, 0x99, 0xe6, 0xfd, 0xc7, 0x33,
+ 0x2f, 0x01, 0x19, 0x6e, 0x5b, 0x29, 0x97, 0xe0, 0x48, 0x37, 0x58, 0xc6, 0x7c, 0xe6, 0x5b, 0x3d,
+ 0x18, 0xca, 0xd3, 0xb2, 0x5f, 0xf5, 0xec, 0x93, 0x30, 0x19, 0xdf, 0x83, 0x87, 0xfa, 0x9e, 0xd6,
+ 0xe0, 0xc1, 0x43, 0xf4, 0xb7, 0xcb, 0xa3, 0x4f, 0xfd, 0x8d, 0xfe, 0xc8, 0x51, 0x9a, 0xb9, 0x3d,
+ 0xba, 0xd0, 0x95, 0xbf, 0x16, 0xfb, 0x98, 0x39, 0x8b, 0x36, 0x8e, 0x6b, 0xc3, 0x1e, 0xed, 0x17,
+ 0xdd, 0x77, 0x72, 0x5f, 0xf4, 0xeb, 0xed, 0x93, 0xea, 0x79, 0x67, 0x2e, 0x70, 0x5d, 0x80, 0x58,
+ 0xb0, 0x30, 0x59, 0x13, 0x0b, 0xd4, 0x69, 0xb8, 0x86, 0x1f, 0x6e, 0x5a, 0x12, 0xe9, 0x9e, 0xe5,
+ 0xc5, 0xd8, 0x87, 0xab, 0xcb, 0x91, 0xc3, 0x62, 0xcd, 0x6e, 0xd9, 0xa6, 0xdd, 0xd8, 0x9d, 0xbf,
+ 0xa3, 0x39, 0x04, 0xdb, 0x6d, 0x4f, 0x60, 0xeb, 0x56, 0x40, 0xfc, 0xc8, 0x00, 0x5c, 0x91, 0xd0,
+ 0xa5, 0x46, 0xe5, 0x3c, 0x8c, 0xaf, 0xc2, 0x6b, 0xf1, 0xe0, 0x99, 0x85, 0xfc, 0x46, 0xa6, 0x07,
+ 0xf5, 0x2b, 0x5f, 0x30, 0x4d, 0xb4, 0xa7, 0x00, 0x34, 0xb5, 0x1d, 0x11, 0xc9, 0x4d, 0x9c, 0x16,
+ 0xf5, 0x63, 0xe9, 0xe0, 0x4a, 0x40, 0x86, 0x77, 0xef, 0x79, 0x5f, 0xcf, 0x19, 0x02, 0x8e, 0x48,
+ 0x02, 0x94, 0x46, 0xd4, 0x73, 0xb4, 0xd0, 0xd9, 0x26, 0x9c, 0x8a, 0xf5, 0xfc, 0x58, 0xdf, 0x19,
+ 0xbf, 0x3c, 0xe4, 0x5f, 0x90, 0x45, 0x88, 0xb9, 0x5f, 0x52, 0xe0, 0x3c, 0xc9, 0x12, 0x38, 0xc5,
+ 0x6d, 0xf9, 0xf9, 0xe3, 0x12, 0x68, 0x45, 0xc2, 0xad, 0x2c, 0x30, 0xce, 0xee, 0x19, 0xda, 0x05,
+ 0x70, 0x83, 0x6f, 0xba, 0x97, 0xb8, 0x15, 0xa9, 0x4c, 0x82, 0xeb, 0x61, 0xc2, 0xdf, 0x58, 0x22,
+ 0x86, 0x7e, 0x4a, 0x81, 0x69, 0x33, 0x85, 0xc3, 0x09, 0x8e, 0x59, 0x3b, 0x86, 0xb3, 0x85, 0x5b,
+ 0xa8, 0xa4, 0x41, 0x70, 0x6a, 0x57, 0xd0, 0xcf, 0x64, 0x86, 0x18, 0xe6, 0x92, 0xc9, 0xda, 0x71,
+ 0x7c, 0x83, 0x39, 0xa2, 0x0d, 0x7f, 0x46, 0x01, 0x54, 0x4f, 0x5c, 0xbe, 0x85, 0x71, 0xe2, 0x33,
+ 0x47, 0xae, 0x62, 0xe0, 0x26, 0x46, 0xc9, 0x72, 0x9c, 0xd2, 0x09, 0xb6, 0xce, 0x5e, 0x0a, 0xcf,
+ 0x17, 0x2e, 0xc0, 0xbd, 0xae, 0x73, 0xda, 0x71, 0xc2, 0xd7, 0x39, 0x0d, 0x82, 0x53, 0xbb, 0xa2,
+ 0xfe, 0xd6, 0x08, 0xd7, 0x05, 0x33, 0x1b, 0x90, 0x97, 0x60, 0x70, 0x43, 0xd3, 0x6f, 0x8b, 0xf7,
+ 0xd7, 0x9c, 0x56, 0x49, 0x0b, 0x0c, 0x03, 0xd7, 0xc2, 0xf0, 0xff, 0xb1, 0xc0, 0x8a, 0x5e, 0x80,
+ 0xbe, 0xba, 0xe5, 0x7b, 0xd8, 0xbf, 0xa7, 0x87, 0xf7, 0x85, 0x30, 0x4e, 0x49, 0x79, 0xb5, 0x86,
+ 0x29, 0x52, 0x64, 0xc1, 0xb0, 0x25, 0x54, 0xa7, 0x42, 0xbb, 0xf5, 0x74, 0x5e, 0x02, 0x81, 0x0a,
+ 0x36, 0x50, 0xfc, 0xfa, 0x25, 0x38, 0xa0, 0x41, 0xe9, 0xc5, 0xde, 0x37, 0x73, 0xd3, 0x0b, 0x5e,
+ 0x84, 0xe4, 0x00, 0xae, 0xf1, 0x57, 0x21, 0x02, 0x83, 0x9e, 0x66, 0x58, 0x9e, 0xef, 0x2d, 0xff,
+ 0x44, 0x5e, 0x6a, 0x6b, 0x14, 0x4b, 0xa8, 0x21, 0x65, 0x3f, 0x5d, 0x2c, 0x90, 0xa3, 0x0d, 0x18,
+ 0xe4, 0x1e, 0xf3, 0xe2, 0x13, 0xca, 0xfd, 0xbe, 0xc6, 0x9d, 0xf0, 0xf9, 0x36, 0xe0, 0xff, 0x63,
+ 0x81, 0x19, 0xbd, 0x0c, 0xc3, 0xae, 0x6f, 0x8e, 0x36, 0xdc, 0xdb, 0xd4, 0x05, 0xb6, 0x68, 0xc2,
+ 0xff, 0x57, 0x18, 0xa1, 0x05, 0xf8, 0xd1, 0x06, 0x0c, 0x19, 0xe2, 0x4a, 0x35, 0x92, 0x7f, 0xdb,
+ 0xf9, 0xd7, 0x25, 0x76, 0xdb, 0xf0, 0x6f, 0x4a, 0x3e, 0xe2, 0x2c, 0x9b, 0x13, 0xf8, 0x06, 0xda,
+ 0x9c, 0xa0, 0x57, 0x00, 0x88, 0xaf, 0x42, 0x77, 0x67, 0x46, 0xf3, 0x6f, 0x19, 0x49, 0x11, 0xef,
+ 0x0b, 0x44, 0x41, 0x91, 0x8b, 0x25, 0x22, 0xe8, 0x55, 0x59, 0x67, 0x37, 0xd6, 0x5b, 0x10, 0x90,
+ 0x64, 0x58, 0x9b, 0xf0, 0xe9, 0x2e, 0x50, 0x17, 0x49, 0xaa, 0x34, 0xf5, 0xcb, 0x00, 0x10, 0x3e,
+ 0xeb, 0xa2, 0x4d, 0x18, 0xf6, 0xa9, 0xf4, 0x12, 0x86, 0xe7, 0xba, 0x00, 0xf3, 0xed, 0xe5, 0xff,
+ 0xc2, 0x01, 0x6e, 0x54, 0x4a, 0x0b, 0x07, 0x15, 0x66, 0xc8, 0xed, 0x2e, 0x14, 0xd4, 0x2b, 0x00,
+ 0x7a, 0x18, 0xe4, 0xb5, 0x2f, 0xff, 0x5a, 0x05, 0x01, 0x60, 0xc3, 0xb5, 0x92, 0x62, 0xc4, 0x4a,
+ 0x44, 0x32, 0xac, 0xd2, 0xfb, 0x73, 0x59, 0xa5, 0x3f, 0x01, 0xa7, 0x84, 0x15, 0x60, 0x85, 0xbd,
+ 0x32, 0x7a, 0xbb, 0xc2, 0x71, 0x93, 0xd9, 0x87, 0x96, 0xa2, 0x20, 0x1c, 0xaf, 0x8b, 0xfe, 0xa5,
+ 0x02, 0xc3, 0xba, 0x10, 0xd0, 0x04, 0x6f, 0x5b, 0xee, 0xed, 0x51, 0x7f, 0xce, 0x97, 0xf7, 0xb8,
+ 0x20, 0xff, 0xac, 0xcf, 0x55, 0xfd, 0xe2, 0x23, 0x12, 0xe3, 0x83, 0x5e, 0xa3, 0xdf, 0x53, 0x60,
+ 0x54, 0x33, 0x4d, 0x5b, 0xd7, 0x3c, 0x16, 0x1e, 0x90, 0x7b, 0x94, 0xde, 0xea, 0x71, 0x14, 0xf3,
+ 0x21, 0x46, 0x3e, 0x90, 0xf7, 0x05, 0x9a, 0x80, 0x10, 0x72, 0x44, 0x63, 0x91, 0xbb, 0x8f, 0xfe,
+ 0x7f, 0x05, 0xee, 0xe7, 0x6e, 0xbc, 0x25, 0x2a, 0x73, 0x6d, 0x1a, 0xba, 0xe6, 0x11, 0x1e, 0xb3,
+ 0xd4, 0x77, 0x21, 0xe3, 0x36, 0xf4, 0xc3, 0x87, 0xb6, 0xa1, 0xbf, 0xba, 0xbf, 0x57, 0xbc, 0xbf,
+ 0xd4, 0x05, 0x6e, 0xdc, 0x55, 0x0f, 0xd0, 0x5d, 0x18, 0x37, 0xe5, 0xf8, 0xe3, 0x82, 0xc9, 0xe7,
+ 0x7a, 0x7e, 0x8d, 0x04, 0x32, 0xe7, 0x0a, 0x86, 0x48, 0x11, 0x8e, 0x92, 0x9a, 0xbd, 0x0d, 0xe3,
+ 0x91, 0x8d, 0x76, 0xac, 0x8a, 0x6b, 0x0b, 0x26, 0xe3, 0xfb, 0xe1, 0x58, 0xef, 0x79, 0x37, 0x61,
+ 0x24, 0x10, 0x16, 0xd0, 0x25, 0x89, 0x50, 0x28, 0x7a, 0xdd, 0x24, 0xbb, 0x9c, 0x6a, 0x31, 0xa2,
+ 0x43, 0xe1, 0x4a, 0x42, 0x16, 0xbd, 0x51, 0x20, 0x54, 0xff, 0x40, 0xbc, 0xaa, 0xae, 0x91, 0x66,
+ 0xcb, 0xd4, 0x3c, 0xf2, 0xc6, 0xb7, 0x43, 0x52, 0xff, 0x83, 0xc2, 0xcf, 0x1b, 0x2e, 0xda, 0x20,
+ 0x0d, 0x46, 0x9b, 0x3c, 0xf9, 0x1d, 0x8b, 0xf5, 0xa8, 0xe4, 0x8f, 0x32, 0xb9, 0x12, 0xa2, 0xc1,
+ 0x32, 0x4e, 0x74, 0x07, 0x46, 0x7c, 0x61, 0xd0, 0xd7, 0xd4, 0x2c, 0xf5, 0x26, 0x9c, 0x05, 0x72,
+ 0x67, 0x70, 0xb4, 0xfa, 0x25, 0x2e, 0x0e, 0x69, 0xa9, 0x1a, 0xa0, 0x64, 0x1b, 0xf4, 0x40, 0xe8,
+ 0xcf, 0xa6, 0x44, 0xd3, 0xd5, 0x24, 0x7c, 0xda, 0x7c, 0x25, 0x6b, 0x21, 0x4b, 0xc9, 0xaa, 0xfe,
+ 0x66, 0x01, 0xa6, 0xc5, 0xd5, 0x73, 0x5e, 0xd7, 0xed, 0xb6, 0xe5, 0x85, 0x6e, 0xc6, 0xdc, 0x77,
+ 0x5f, 0x10, 0x61, 0xe2, 0x24, 0x77, 0xec, 0xc7, 0x02, 0x82, 0x6e, 0x71, 0xed, 0xa7, 0x55, 0x5f,
+ 0xb3, 0x6f, 0x13, 0x2b, 0xe4, 0x12, 0x72, 0x90, 0x8c, 0xc5, 0xb4, 0x0a, 0x38, 0xbd, 0x1d, 0xda,
+ 0x06, 0xd4, 0xd4, 0x76, 0xe2, 0xd8, 0xf2, 0x25, 0x41, 0x63, 0xf7, 0xc5, 0x95, 0x04, 0x36, 0x9c,
+ 0x42, 0x81, 0x1e, 0xa4, 0x54, 0x92, 0x6b, 0x79, 0xa4, 0xce, 0x87, 0xe8, 0x1b, 0x75, 0xb0, 0x83,
+ 0x74, 0x3e, 0x0a, 0xc2, 0xf1, 0xba, 0xea, 0xc7, 0x06, 0xe1, 0x7c, 0x74, 0x12, 0xe9, 0x17, 0xea,
+ 0xbb, 0xd7, 0x3f, 0xe5, 0xfb, 0x8e, 0xf1, 0x89, 0x7c, 0x20, 0xee, 0x3b, 0x36, 0x23, 0x1b, 0x0d,
+ 0x89, 0x46, 0x11, 0x3f, 0xb2, 0x6f, 0x80, 0xaf, 0x7c, 0x86, 0x73, 0x74, 0xdf, 0xb1, 0xc6, 0x04,
+ 0xf8, 0xa4, 0x02, 0xb3, 0xd1, 0xe2, 0x25, 0xc3, 0x32, 0xdc, 0x2d, 0x91, 0xf7, 0xe4, 0xf0, 0xae,
+ 0x6b, 0x2c, 0x73, 0xf2, 0x72, 0x26, 0x46, 0xdc, 0x81, 0x1a, 0xfa, 0x01, 0x05, 0x2e, 0xc4, 0xe6,
+ 0x25, 0x92, 0x85, 0xe5, 0xf0, 0x5e, 0x6c, 0x2c, 0xb8, 0xcb, 0x72, 0x36, 0x4a, 0xdc, 0x89, 0x5e,
+ 0xa7, 0x88, 0x9f, 0x83, 0xaf, 0x97, 0x88, 0x9f, 0xbf, 0x58, 0x80, 0x01, 0x66, 0x37, 0xf5, 0xc6,
+ 0x70, 0x38, 0x62, 0x5d, 0xcd, 0xb4, 0x77, 0x6d, 0xc4, 0xec, 0x5d, 0x9f, 0xca, 0x4f, 0xa2, 0xb3,
+ 0xc1, 0xeb, 0xfb, 0xe0, 0x2c, 0xab, 0x36, 0x5f, 0x67, 0x8a, 0x36, 0x97, 0xd4, 0xe7, 0xeb, 0x75,
+ 0x76, 0xbd, 0x3d, 0xf8, 0x8d, 0xec, 0x12, 0xf4, 0xb5, 0x1d, 0x33, 0x1e, 0x42, 0x76, 0x1d, 0x2f,
+ 0x63, 0x5a, 0xae, 0x7e, 0x52, 0x81, 0x49, 0x86, 0x5b, 0x62, 0x31, 0x68, 0x1b, 0x86, 0x1d, 0xc1,
+ 0x66, 0xc4, 0xda, 0x2c, 0xe7, 0x1e, 0x5a, 0x0a, 0xeb, 0xe2, 0x37, 0x36, 0xff, 0x17, 0x0e, 0x68,
+ 0xa9, 0x7f, 0x3a, 0x00, 0x33, 0x59, 0x8d, 0xd0, 0x8f, 0x28, 0x70, 0x56, 0x0f, 0x25, 0xce, 0xf9,
+ 0xb6, 0xb7, 0x65, 0x3b, 0x7e, 0x46, 0x85, 0xdc, 0xea, 0x90, 0xd2, 0x7c, 0xd0, 0x2b, 0x96, 0x46,
+ 0xa4, 0x94, 0x4a, 0x01, 0x67, 0x50, 0x46, 0xaf, 0x02, 0xb8, 0xee, 0xd6, 0x4d, 0xb2, 0xdb, 0xd2,
+ 0x0c, 0xdf, 0x72, 0xeb, 0x66, 0xfe, 0x6d, 0x50, 0xbb, 0x21, 0x50, 0x05, 0x9d, 0xe2, 0xba, 0xea,
+ 0xb0, 0x5c, 0x22, 0x87, 0x3e, 0xaa, 0xc0, 0xb8, 0x2d, 0xc7, 0x6b, 0xe9, 0xc5, 0x98, 0x3f, 0x35,
+ 0xf0, 0x0b, 0x97, 0xb4, 0xa3, 0xa0, 0x28, 0x49, 0xba, 0x2c, 0x53, 0x6e, 0xfc, 0x64, 0x13, 0xbc,
+ 0x6f, 0x25, 0x9f, 0x0c, 0x94, 0x71, 0x4c, 0xf2, 0x5b, 0x7b, 0x12, 0x9c, 0x24, 0xcf, 0x3a, 0x45,
+ 0x3c, 0xbd, 0xbe, 0x68, 0xe9, 0xce, 0x2e, 0x8b, 0x10, 0x40, 0x3b, 0x35, 0x98, 0xbf, 0x53, 0x8b,
+ 0x6b, 0xa5, 0x72, 0x04, 0x59, 0xb4, 0x53, 0x49, 0x70, 0x92, 0xbc, 0xfa, 0x91, 0x02, 0x9c, 0x63,
+ 0xcb, 0x7c, 0xb3, 0xbd, 0x41, 0xb8, 0xf1, 0xd5, 0x3f, 0xb8, 0x00, 0x3b, 0xbf, 0xa3, 0xc0, 0x08,
+ 0x9b, 0x83, 0x37, 0x88, 0x8f, 0x26, 0xeb, 0x6b, 0x86, 0x81, 0xf3, 0x6f, 0x2b, 0x30, 0x95, 0xc8,
+ 0x21, 0xd5, 0x95, 0x87, 0xdf, 0x89, 0xd9, 0xde, 0xbe, 0x25, 0xcc, 0x5b, 0xd9, 0x17, 0x06, 0xb6,
+ 0x88, 0xe7, 0xac, 0x54, 0x9f, 0x83, 0xf1, 0x88, 0x7d, 0xb3, 0x14, 0x02, 0x32, 0x2d, 0x78, 0xa5,
+ 0x1c, 0xe1, 0xb1, 0xd0, 0x29, 0x36, 0x65, 0xb8, 0xe5, 0x93, 0x9c, 0xed, 0x1f, 0xce, 0x96, 0x47,
+ 0x62, 0xcb, 0xfb, 0xcf, 0x38, 0x2c, 0xb0, 0xa4, 0xdb, 0xcb, 0x33, 0x0e, 0x8b, 0x50, 0x29, 0x02,
+ 0xc1, 0xf2, 0xff, 0xb1, 0xc0, 0x8a, 0x9e, 0x8e, 0x86, 0x79, 0x5d, 0x0d, 0xef, 0x76, 0xd3, 0xf1,
+ 0xe0, 0xac, 0x6c, 0x4b, 0x26, 0x6a, 0x23, 0xcc, 0x1f, 0x82, 0xf8, 0x59, 0x96, 0x2b, 0xbb, 0x4d,
+ 0x79, 0xb5, 0xc6, 0xe3, 0xff, 0x05, 0x0f, 0x40, 0x51, 0x8d, 0x77, 0xff, 0x49, 0x68, 0xbc, 0x1d,
+ 0x18, 0xdd, 0x32, 0x36, 0x88, 0x63, 0x71, 0x31, 0x66, 0x20, 0xbf, 0x84, 0x76, 0x23, 0x44, 0xc3,
+ 0xd5, 0x00, 0x52, 0x01, 0x96, 0x89, 0x20, 0x27, 0x12, 0xac, 0x7a, 0x30, 0xbf, 0x54, 0x12, 0xaa,
+ 0xa6, 0xc3, 0x71, 0x66, 0x04, 0xaa, 0xb6, 0x00, 0xac, 0x20, 0x82, 0x6b, 0x2f, 0x0f, 0x43, 0x61,
+ 0x1c, 0x58, 0x2e, 0x74, 0x84, 0xbf, 0xb1, 0x44, 0x81, 0xce, 0x6b, 0x33, 0x4c, 0x68, 0x20, 0xd4,
+ 0x8c, 0x4f, 0xf5, 0x98, 0x54, 0x42, 0xa8, 0x57, 0xc2, 0x02, 0x2c, 0x13, 0xa1, 0x63, 0x6c, 0x06,
+ 0x61, 0xfc, 0x85, 0x1a, 0x31, 0xd7, 0x18, 0xc3, 0x64, 0x00, 0x7c, 0x8c, 0xe1, 0x6f, 0x2c, 0x51,
+ 0x40, 0x2f, 0x4b, 0xef, 0x87, 0x90, 0x5f, 0x49, 0xd5, 0xd5, 0xdb, 0xe1, 0x3b, 0x43, 0x5d, 0xcd,
+ 0x28, 0xfb, 0x4e, 0x2f, 0x48, 0x7a, 0x1a, 0x96, 0xde, 0x80, 0xf2, 0x8e, 0x84, 0xde, 0x26, 0xf4,
+ 0xaa, 0x18, 0xeb, 0xe8, 0x55, 0x51, 0xa2, 0xd2, 0x99, 0xe4, 0x99, 0xc8, 0x18, 0xc2, 0x78, 0xf8,
+ 0x08, 0x52, 0x8b, 0x03, 0x71, 0xb2, 0x3e, 0x67, 0xf8, 0xa4, 0xce, 0xda, 0x4e, 0xc8, 0x0c, 0x9f,
+ 0x97, 0xe1, 0x00, 0x8a, 0xb6, 0x61, 0xcc, 0x95, 0x5c, 0x34, 0x66, 0x4e, 0xf5, 0xfa, 0x84, 0x28,
+ 0xdc, 0x33, 0x98, 0x2d, 0xa4, 0x5c, 0x82, 0x23, 0x74, 0xa2, 0xef, 0x5b, 0x93, 0x27, 0xfb, 0xbe,
+ 0x85, 0xda, 0x51, 0xeb, 0xeb, 0xa9, 0x23, 0x89, 0xe3, 0x72, 0xa0, 0x75, 0x36, 0x5d, 0x5a, 0xb2,
+ 0xd3, 0xb2, 0xdd, 0xb6, 0x43, 0x98, 0xd9, 0x27, 0x5b, 0x1e, 0x14, 0x2e, 0xed, 0x62, 0x1c, 0x88,
+ 0x93, 0xf5, 0xd1, 0xf7, 0x29, 0x30, 0xe9, 0xee, 0xba, 0x1e, 0x69, 0xd2, 0x63, 0xcb, 0xb6, 0x88,
+ 0xe5, 0xb9, 0x33, 0xa7, 0xf3, 0xc7, 0x05, 0xaf, 0xc5, 0x70, 0xf1, 0x63, 0x27, 0x5e, 0x8a, 0x13,
+ 0x34, 0xe9, 0xce, 0x91, 0x23, 0xc1, 0xcc, 0x4c, 0xe7, 0xdf, 0x39, 0x72, 0x94, 0x19, 0xbe, 0x73,
+ 0xe4, 0x12, 0x1c, 0xa1, 0x83, 0x1e, 0x85, 0x71, 0xd7, 0xcf, 0x61, 0xce, 0x66, 0xf0, 0x4c, 0x18,
+ 0xac, 0xb3, 0x26, 0x03, 0x70, 0xb4, 0x1e, 0xfa, 0x10, 0x8c, 0xc9, 0x67, 0xe7, 0xcc, 0xd9, 0xa3,
+ 0x0e, 0x5b, 0xcf, 0x7b, 0x2e, 0x83, 0x22, 0x04, 0x11, 0x86, 0xb3, 0x92, 0xf3, 0xa0, 0xfc, 0x7d,
+ 0x9f, 0x63, 0x43, 0xe0, 0xf7, 0xd9, 0xd4, 0x1a, 0x38, 0xa3, 0x25, 0xfa, 0x89, 0xf4, 0xe7, 0xf2,
+ 0x19, 0xb6, 0xa5, 0xab, 0x47, 0xf2, 0x5c, 0xfe, 0x9c, 0xe1, 0x6d, 0xdd, 0x6a, 0xf1, 0xc8, 0x62,
+ 0x87, 0x7c, 0x39, 0x57, 0xff, 0x48, 0x01, 0x08, 0x14, 0x26, 0x27, 0xf1, 0x54, 0x51, 0x8f, 0xe8,
+ 0x90, 0x16, 0x7a, 0x52, 0xf0, 0x64, 0x66, 0x25, 0x51, 0xbf, 0xa2, 0xc0, 0x44, 0x58, 0xed, 0x04,
+ 0xae, 0x46, 0x7a, 0xf4, 0x6a, 0xf4, 0x64, 0x6f, 0xe3, 0xca, 0xb8, 0x1f, 0xfd, 0xcf, 0x82, 0x3c,
+ 0x2a, 0x26, 0xfd, 0x6e, 0x47, 0x9e, 0xfe, 0x29, 0xe9, 0x1b, 0xbd, 0x3c, 0xfd, 0xcb, 0xd1, 0x37,
+ 0xc2, 0xf1, 0xa6, 0x98, 0x02, 0x7c, 0x77, 0x44, 0xfe, 0xec, 0x21, 0xee, 0x4d, 0x20, 0x6c, 0xfa,
+ 0xa4, 0xf9, 0x04, 0x1c, 0x24, 0x8c, 0xbe, 0x22, 0x1f, 0x4f, 0x3d, 0x64, 0x12, 0x89, 0x0c, 0xb8,
+ 0xb3, 0xd1, 0xc5, 0x2f, 0x4e, 0xc1, 0xa8, 0xa4, 0x5b, 0x8c, 0x19, 0x32, 0x28, 0x27, 0x61, 0xc8,
+ 0xe0, 0xc1, 0xa8, 0x1e, 0xa4, 0x92, 0xf4, 0xa7, 0xbd, 0x47, 0x9a, 0xc1, 0xb1, 0x18, 0x26, 0xa9,
+ 0x74, 0xb1, 0x4c, 0x86, 0x0a, 0x6f, 0xc1, 0x1e, 0xeb, 0x3b, 0x02, 0xf3, 0x92, 0x4e, 0xfb, 0xea,
+ 0x11, 0x00, 0x5f, 0xfe, 0x27, 0x75, 0x11, 0xa1, 0x3d, 0x30, 0x9d, 0xae, 0xb8, 0x37, 0x02, 0x18,
+ 0x96, 0xea, 0x25, 0x1f, 0xc6, 0x07, 0x4e, 0xec, 0x61, 0x9c, 0x6e, 0x03, 0xd3, 0x4f, 0xba, 0xdf,
+ 0x93, 0xb9, 0x5a, 0x90, 0xba, 0x3f, 0xdc, 0x06, 0x41, 0x91, 0x8b, 0x25, 0x22, 0x19, 0xf6, 0x2c,
+ 0x43, 0xb9, 0xec, 0x59, 0xda, 0x70, 0xda, 0x21, 0x9e, 0xb3, 0x5b, 0xda, 0xd5, 0x59, 0x6a, 0x13,
+ 0xc7, 0x63, 0x37, 0xf8, 0xe1, 0x7c, 0x01, 0x13, 0x71, 0x12, 0x15, 0x4e, 0xc3, 0x1f, 0x11, 0x80,
+ 0x47, 0x3a, 0x0a, 0xc0, 0xef, 0x84, 0x51, 0x8f, 0xe8, 0x5b, 0x96, 0xa1, 0x6b, 0x66, 0xa5, 0x2c,
+ 0xe2, 0x77, 0x87, 0xb2, 0x5c, 0x08, 0xc2, 0x72, 0x3d, 0xb4, 0x00, 0x7d, 0x6d, 0xa3, 0x2e, 0x6e,
+ 0x00, 0xdf, 0x16, 0x68, 0xe9, 0x2b, 0xe5, 0x7b, 0x7b, 0xc5, 0x37, 0x87, 0x06, 0x22, 0xc1, 0xa8,
+ 0xae, 0xb5, 0x6e, 0x37, 0xae, 0x79, 0xbb, 0x2d, 0xe2, 0xce, 0xad, 0x57, 0xca, 0x98, 0x36, 0x4e,
+ 0xb3, 0xf5, 0x19, 0x3b, 0x84, 0xad, 0xcf, 0x67, 0x14, 0x38, 0xad, 0xc5, 0x1f, 0x18, 0x88, 0x3b,
+ 0x33, 0x9e, 0x9f, 0x5b, 0xa6, 0x3f, 0x5a, 0x2c, 0x5c, 0x10, 0xe3, 0x3b, 0x3d, 0x9f, 0x24, 0x87,
+ 0xd3, 0xfa, 0x80, 0x1c, 0x40, 0x4d, 0xa3, 0x11, 0xe4, 0xbf, 0x17, 0xab, 0x3e, 0x91, 0x4f, 0x6f,
+ 0xb3, 0x92, 0xc0, 0x84, 0x53, 0xb0, 0xa3, 0x3b, 0x30, 0x2a, 0x09, 0x49, 0xe2, 0x26, 0x53, 0x3e,
+ 0x8a, 0x77, 0x10, 0x7e, 0xdb, 0x95, 0xdf, 0x38, 0x64, 0x4a, 0xc1, 0x23, 0xa7, 0xa4, 0x66, 0x10,
+ 0x0f, 0x7d, 0x6c, 0xd4, 0x93, 0xf9, 0x1f, 0x39, 0xd3, 0x31, 0xe2, 0x0e, 0xd4, 0x58, 0x98, 0x42,
+ 0x0a, 0x96, 0xee, 0xe6, 0x33, 0x53, 0xf9, 0xe3, 0xac, 0x2c, 0x47, 0x51, 0xf1, 0xad, 0x19, 0x2b,
+ 0xc4, 0x71, 0x82, 0x68, 0x09, 0x10, 0xe1, 0xaa, 0xf4, 0xf0, 0x72, 0xe6, 0xce, 0x20, 0xf6, 0xfe,
+ 0xce, 0x96, 0x74, 0x31, 0x01, 0xc5, 0x29, 0x2d, 0x90, 0x17, 0xd1, 0x95, 0xf4, 0x70, 0xcb, 0x89,
+ 0xe7, 0xcc, 0xe9, 0xa8, 0x31, 0xf9, 0x5e, 0x25, 0x91, 0x44, 0x99, 0x5f, 0x6e, 0x6e, 0xf4, 0x9e,
+ 0x44, 0x59, 0x90, 0xef, 0x26, 0x95, 0xf2, 0xe7, 0x15, 0x38, 0xd7, 0x4c, 0x4f, 0x16, 0xc9, 0xee,
+ 0x3c, 0x39, 0x1f, 0xae, 0x32, 0xf2, 0x4f, 0x32, 0x35, 0x46, 0x56, 0x72, 0x4a, 0x9c, 0xd5, 0x11,
+ 0xf5, 0x0f, 0x15, 0xa1, 0x8a, 0x3e, 0x41, 0x73, 0xa4, 0xe3, 0x7e, 0x27, 0x56, 0x9f, 0x83, 0x99,
+ 0x9a, 0x1f, 0x64, 0xb4, 0x1e, 0xcb, 0x25, 0xf0, 0x1e, 0x18, 0xe7, 0x4f, 0x41, 0x2b, 0x5a, 0x6b,
+ 0x35, 0x7c, 0x37, 0x08, 0xc2, 0x51, 0x94, 0x64, 0x20, 0x8e, 0xd6, 0x55, 0xbf, 0xa6, 0xc0, 0xb9,
+ 0x28, 0x66, 0xdb, 0x31, 0xee, 0xf6, 0x8e, 0x18, 0x7d, 0x5c, 0x81, 0xd1, 0xdb, 0xc1, 0x2b, 0x95,
+ 0x2f, 0xba, 0xe5, 0x72, 0xd9, 0xf0, 0x7b, 0x45, 0x1c, 0xe9, 0xd9, 0x2b, 0x99, 0xa0, 0x32, 0x04,
+ 0xba, 0x58, 0x26, 0xad, 0xfe, 0x17, 0x05, 0x12, 0xea, 0x03, 0xb4, 0x01, 0x43, 0x94, 0x48, 0x79,
+ 0xb5, 0x26, 0xf6, 0xc4, 0x7b, 0xf2, 0x49, 0x95, 0x0c, 0x05, 0x7f, 0x14, 0x11, 0x3f, 0xb0, 0x8f,
+ 0x18, 0x6d, 0x73, 0xff, 0x7f, 0x3f, 0xd1, 0x90, 0xd8, 0x1e, 0xb9, 0xc4, 0x76, 0x39, 0x61, 0x11,
+ 0xbf, 0xd6, 0xcb, 0x25, 0x38, 0x42, 0x47, 0x5d, 0x06, 0x08, 0x55, 0x3e, 0x3d, 0x9b, 0xf7, 0xfd,
+ 0xdb, 0xd3, 0x70, 0xa6, 0x67, 0x67, 0xc4, 0x8f, 0x2a, 0x70, 0x96, 0x6c, 0x1b, 0xba, 0x37, 0xbf,
+ 0xe9, 0x11, 0xe7, 0xd6, 0xad, 0x95, 0xb5, 0x2d, 0x87, 0xb8, 0x5b, 0xb6, 0x59, 0xef, 0xc6, 0x98,
+ 0x31, 0xc5, 0xf2, 0x8a, 0xa9, 0x26, 0x16, 0x53, 0x31, 0xe2, 0x0c, 0x4a, 0x4c, 0xdd, 0xb5, 0xcd,
+ 0x15, 0x01, 0x98, 0xde, 0xb9, 0xda, 0x8e, 0xeb, 0x89, 0xb8, 0x81, 0x5c, 0xdd, 0x15, 0x07, 0xe2,
+ 0x64, 0xfd, 0x38, 0x12, 0x96, 0x45, 0x8f, 0xc9, 0xed, 0x4a, 0x12, 0x09, 0x03, 0xe2, 0x64, 0x7d,
+ 0x19, 0x09, 0x5f, 0x29, 0x7a, 0x28, 0x0e, 0x24, 0x91, 0x04, 0x40, 0x9c, 0xac, 0x8f, 0xea, 0x70,
+ 0xd1, 0x21, 0xba, 0xdd, 0x6c, 0x12, 0xab, 0xce, 0x26, 0x65, 0x45, 0x73, 0x1a, 0x86, 0xb5, 0xe4,
+ 0x68, 0xac, 0x22, 0x7b, 0x3d, 0x50, 0x58, 0xc2, 0xdb, 0x8b, 0xb8, 0x43, 0x3d, 0xdc, 0x11, 0x0b,
+ 0x6a, 0xc2, 0xa9, 0x36, 0xe3, 0xff, 0x0e, 0x8b, 0x2b, 0xb6, 0xad, 0x99, 0xe2, 0x89, 0xe0, 0xb0,
+ 0x2b, 0xc6, 0x0e, 0xea, 0xf5, 0x28, 0x2a, 0x1c, 0xc7, 0x8d, 0x76, 0xa9, 0x78, 0x2e, 0xba, 0x23,
+ 0x91, 0x1c, 0xce, 0x45, 0x52, 0x88, 0xe8, 0x09, 0x74, 0x38, 0x8d, 0x06, 0xaa, 0xc0, 0x69, 0x4f,
+ 0x73, 0x1a, 0xc4, 0x2b, 0x55, 0xd7, 0xab, 0xc4, 0xd1, 0x29, 0x8f, 0x35, 0xb9, 0xb4, 0xae, 0x70,
+ 0x54, 0x6b, 0x49, 0x30, 0x4e, 0x6b, 0x83, 0x3e, 0x04, 0x6f, 0x89, 0x4e, 0xea, 0xb2, 0x7d, 0x87,
+ 0x38, 0x0b, 0x76, 0xdb, 0xaa, 0x47, 0x91, 0x03, 0x43, 0xfe, 0xc0, 0xfe, 0x5e, 0xf1, 0x2d, 0xb8,
+ 0x9b, 0x06, 0xb8, 0x3b, 0xbc, 0xc9, 0x0e, 0xac, 0xb7, 0x5a, 0xa9, 0x1d, 0x18, 0xcd, 0xea, 0x40,
+ 0x46, 0x03, 0xdc, 0x1d, 0x5e, 0x84, 0xe1, 0x2c, 0x9f, 0x18, 0x9e, 0x9e, 0x59, 0xa2, 0x38, 0xc6,
+ 0x28, 0xb2, 0xef, 0x77, 0x2d, 0xb5, 0x06, 0xce, 0x68, 0x49, 0xcf, 0x94, 0xab, 0x59, 0xc3, 0x4f,
+ 0x90, 0x19, 0x67, 0x64, 0xde, 0xb6, 0xbf, 0x57, 0xbc, 0x8a, 0xbb, 0x6c, 0x83, 0xbb, 0xc6, 0x9e,
+ 0xd2, 0x95, 0x70, 0x22, 0x12, 0x5d, 0x99, 0xc8, 0xea, 0x4a, 0x76, 0x1b, 0xdc, 0x35, 0x76, 0xf4,
+ 0xfd, 0x0a, 0x9c, 0xd7, 0x5b, 0xed, 0x1b, 0x86, 0xeb, 0xd9, 0x0d, 0x47, 0x6b, 0x96, 0x89, 0xae,
+ 0xed, 0xde, 0xd0, 0xcc, 0xcd, 0x65, 0x63, 0x93, 0x88, 0x4b, 0xc7, 0x61, 0x3f, 0x1c, 0xe6, 0x78,
+ 0x5b, 0xaa, 0xae, 0xa7, 0x23, 0xc5, 0xd9, 0xf4, 0xd0, 0x8f, 0x2a, 0x70, 0xb1, 0xc9, 0xba, 0x98,
+ 0xd1, 0xa1, 0xc9, 0x5c, 0x1d, 0x62, 0x5c, 0x6c, 0xa5, 0x03, 0x5e, 0xdc, 0x91, 0x2a, 0x9b, 0x24,
+ 0x5e, 0x61, 0xbe, 0xd1, 0x70, 0x48, 0x83, 0x61, 0x0d, 0xb8, 0xcb, 0x54, 0xfe, 0x49, 0x5a, 0xc9,
+ 0x42, 0x8a, 0xb3, 0xe9, 0xa1, 0x97, 0xe1, 0x72, 0x26, 0xb0, 0x64, 0xb7, 0x2d, 0x8f, 0x3d, 0xc2,
+ 0xf4, 0x2d, 0xa8, 0xfb, 0x7b, 0xc5, 0xcb, 0x2b, 0x1d, 0x6b, 0xe2, 0x03, 0x30, 0xb1, 0xd8, 0x23,
+ 0x91, 0x30, 0x00, 0xa7, 0x99, 0x24, 0xf6, 0x62, 0xae, 0x74, 0xbc, 0x47, 0xe8, 0xfb, 0xff, 0x95,
+ 0xa8, 0xef, 0xff, 0x34, 0xeb, 0xd5, 0xfb, 0x8e, 0xae, 0x57, 0xdf, 0x74, 0xf8, 0xef, 0xc6, 0x11,
+ 0xe4, 0x33, 0x0a, 0x08, 0xff, 0x4d, 0x74, 0x31, 0x62, 0x76, 0x34, 0x1c, 0x33, 0x39, 0xf2, 0xb3,
+ 0xe2, 0x16, 0x52, 0xb3, 0xe2, 0xbe, 0x55, 0x0a, 0xc2, 0x3c, 0x12, 0x5e, 0x96, 0x38, 0xe6, 0x30,
+ 0x0a, 0x33, 0x7a, 0x10, 0x46, 0x82, 0x4b, 0xb5, 0x50, 0x76, 0xb2, 0x8c, 0x34, 0xe1, 0xed, 0x3b,
+ 0x84, 0xab, 0xbf, 0xaf, 0x00, 0x84, 0xc9, 0x9e, 0xd1, 0x7d, 0x7e, 0xb0, 0x1a, 0xde, 0xc1, 0xe0,
+ 0xc5, 0x40, 0x0e, 0x58, 0x73, 0xb0, 0x33, 0x02, 0x52, 0x61, 0xb0, 0xcd, 0xd2, 0x5b, 0x0a, 0x07,
+ 0x02, 0x66, 0x02, 0xb3, 0xce, 0x4a, 0xb0, 0x80, 0xa0, 0x75, 0x18, 0x6a, 0x1a, 0x16, 0xf3, 0xf5,
+ 0xe8, 0xcf, 0xe5, 0xeb, 0xc1, 0xee, 0x03, 0x2b, 0x1c, 0x05, 0xf6, 0x71, 0xa9, 0xbf, 0xa4, 0xc0,
+ 0xa9, 0x68, 0x54, 0x6c, 0x16, 0xf2, 0x46, 0x04, 0x4b, 0x15, 0xc1, 0xf8, 0x59, 0x53, 0x11, 0x04,
+ 0x12, 0xfb, 0xb0, 0xe8, 0xeb, 0x74, 0x0f, 0xaf, 0x0f, 0xe9, 0xc1, 0xb9, 0x0f, 0x78, 0x08, 0xf8,
+ 0xf1, 0xd3, 0x30, 0xc8, 0x2f, 0xda, 0x54, 0x8e, 0x4f, 0x09, 0x7e, 0x75, 0x33, 0x7f, 0xbe, 0x89,
+ 0x3c, 0x11, 0x71, 0xe4, 0xac, 0x9b, 0x85, 0x8e, 0x59, 0x37, 0x31, 0xf4, 0xe9, 0x8e, 0xd1, 0x8b,
+ 0x25, 0x52, 0x09, 0x57, 0xb8, 0x25, 0x52, 0x09, 0x57, 0x30, 0x45, 0x86, 0xbc, 0x88, 0x89, 0x4e,
+ 0x7f, 0x7e, 0x15, 0x10, 0x9f, 0x00, 0xc9, 0x50, 0x67, 0xa2, 0xa3, 0x91, 0x8e, 0x1f, 0x69, 0x7f,
+ 0x20, 0xbf, 0x73, 0x90, 0x98, 0xf2, 0x6e, 0x22, 0xed, 0xfb, 0x1f, 0xd2, 0x60, 0xe6, 0x87, 0xb4,
+ 0x09, 0x43, 0xe2, 0x53, 0x10, 0x17, 0x82, 0xf7, 0xf4, 0x90, 0x5b, 0x5e, 0xca, 0x62, 0xc5, 0x0b,
+ 0xb0, 0x8f, 0x9c, 0xde, 0x32, 0x9b, 0xda, 0x8e, 0xd1, 0x6c, 0x37, 0xd9, 0x2d, 0x60, 0x40, 0xae,
+ 0xca, 0x8a, 0xb1, 0x0f, 0x67, 0x55, 0xb9, 0x4f, 0x15, 0x93, 0xda, 0xe5, 0xaa, 0xbc, 0x18, 0xfb,
+ 0x70, 0xf4, 0x02, 0x0c, 0x37, 0xb5, 0x9d, 0x5a, 0xdb, 0x69, 0x10, 0x61, 0xa0, 0x93, 0xad, 0x14,
+ 0x6a, 0x7b, 0x86, 0x39, 0x67, 0x58, 0x9e, 0xeb, 0x39, 0x73, 0x15, 0xcb, 0xbb, 0xe5, 0xd4, 0x3c,
+ 0x66, 0x00, 0xc4, 0x76, 0xdd, 0x8a, 0xc0, 0x82, 0x03, 0x7c, 0xc8, 0x84, 0x89, 0xa6, 0xb6, 0xb3,
+ 0x6e, 0x69, 0x3c, 0x89, 0x82, 0x90, 0xb2, 0xf3, 0x50, 0x60, 0x5a, 0xb9, 0x95, 0x08, 0x2e, 0x1c,
+ 0xc3, 0x9d, 0x62, 0x0c, 0x3a, 0x76, 0x5c, 0xc6, 0xa0, 0xf3, 0x41, 0x94, 0x02, 0xae, 0xd2, 0x3f,
+ 0x9f, 0x1a, 0x1f, 0xb0, 0x63, 0x04, 0x82, 0x97, 0x82, 0x08, 0x04, 0x13, 0xf9, 0xad, 0x17, 0x3b,
+ 0x44, 0x1f, 0x68, 0xc3, 0x68, 0x5d, 0xf3, 0x34, 0x5e, 0xea, 0xce, 0x9c, 0xca, 0xff, 0x3a, 0x5d,
+ 0x0e, 0xd0, 0x84, 0x2c, 0x29, 0x2c, 0x73, 0xb1, 0x4c, 0x07, 0xdd, 0x82, 0x33, 0xf4, 0x63, 0x35,
+ 0x89, 0x17, 0x56, 0x61, 0x3a, 0xb3, 0x49, 0xf6, 0xfd, 0x30, 0x2f, 0xb5, 0x9b, 0x69, 0x15, 0x70,
+ 0x7a, 0xbb, 0x30, 0x96, 0xed, 0x54, 0x7a, 0x2c, 0x5b, 0xf4, 0xa9, 0x34, 0xb3, 0x1b, 0xc4, 0xe6,
+ 0xf4, 0xbd, 0xf9, 0x79, 0x43, 0x6e, 0xe3, 0x9b, 0x7f, 0xae, 0xc0, 0x8c, 0xd8, 0x65, 0xc2, 0x54,
+ 0xc6, 0x24, 0xce, 0x8a, 0x66, 0x69, 0x0d, 0xe2, 0x08, 0x3d, 0xf9, 0x5a, 0x0f, 0xfc, 0x21, 0x81,
+ 0x33, 0x08, 0x0d, 0x71, 0xff, 0xfe, 0x5e, 0xf1, 0xca, 0x41, 0xb5, 0x70, 0x66, 0xdf, 0x90, 0x03,
+ 0x43, 0xee, 0xae, 0xab, 0x7b, 0xa6, 0x2b, 0x64, 0xd0, 0xeb, 0x3d, 0x70, 0xd6, 0x1a, 0xc7, 0xc4,
+ 0x59, 0x6b, 0x98, 0x3b, 0x91, 0x97, 0x62, 0x9f, 0x10, 0xfa, 0x61, 0x05, 0xa6, 0xc4, 0xe3, 0x99,
+ 0x14, 0x7a, 0xe7, 0x4c, 0x7e, 0x3f, 0x99, 0x52, 0x1c, 0x99, 0x6f, 0x1e, 0xc3, 0xb4, 0x49, 0x09,
+ 0x28, 0x4e, 0x52, 0xa7, 0x87, 0x6a, 0xcb, 0x31, 0x6c, 0xc7, 0xf0, 0x76, 0x99, 0x21, 0xd2, 0x80,
+ 0x1f, 0xc1, 0x9e, 0x97, 0xe1, 0x00, 0x8a, 0x6a, 0x30, 0xc1, 0xb5, 0x36, 0x35, 0xcf, 0xd1, 0x3c,
+ 0xd2, 0xd8, 0x15, 0xd6, 0x42, 0x0f, 0xb2, 0x1c, 0xc3, 0x11, 0xc8, 0xbd, 0xbd, 0xe2, 0x19, 0xb1,
+ 0x36, 0x51, 0x00, 0x8e, 0xa1, 0x40, 0x1f, 0x88, 0x19, 0x6f, 0xcd, 0xe4, 0xcf, 0x3f, 0xc8, 0xd7,
+ 0xe2, 0x30, 0x26, 0x5c, 0xbd, 0x46, 0x93, 0xeb, 0x21, 0x07, 0xcc, 0xec, 0xe3, 0x30, 0x26, 0xef,
+ 0x9a, 0x43, 0x05, 0xb1, 0xf3, 0x00, 0x25, 0x07, 0x7b, 0xdc, 0x71, 0x7e, 0xd4, 0x9f, 0x56, 0x60,
+ 0x32, 0x2e, 0xbb, 0xa0, 0x2d, 0x18, 0x12, 0x8c, 0x4c, 0x50, 0x9d, 0xcf, 0x6b, 0xb5, 0x6c, 0x12,
+ 0xe1, 0x1e, 0xcc, 0x45, 0x61, 0x51, 0x84, 0x7d, 0xf4, 0xb2, 0x47, 0x42, 0xa1, 0x83, 0x47, 0xc2,
+ 0x13, 0x70, 0x36, 0x9d, 0xa5, 0xd1, 0x8b, 0x84, 0x46, 0xef, 0x57, 0x42, 0x69, 0x1d, 0x5c, 0x24,
+ 0xd8, 0xa5, 0x0b, 0x73, 0x98, 0xfa, 0x41, 0x88, 0xe7, 0x3e, 0x43, 0x2f, 0xc3, 0x88, 0xeb, 0x6e,
+ 0x71, 0x3b, 0x33, 0x31, 0xc8, 0x7c, 0x4f, 0x3d, 0x7e, 0x1e, 0x1a, 0x7e, 0xf7, 0x09, 0x7e, 0xe2,
+ 0x10, 0xfd, 0xc2, 0xf3, 0x5f, 0xfa, 0xda, 0xe5, 0x37, 0xfd, 0xc1, 0xd7, 0x2e, 0xbf, 0xe9, 0xab,
+ 0x5f, 0xbb, 0xfc, 0xa6, 0x0f, 0xef, 0x5f, 0x56, 0xbe, 0xb4, 0x7f, 0x59, 0xf9, 0x83, 0xfd, 0xcb,
+ 0xca, 0x57, 0xf7, 0x2f, 0x2b, 0x7f, 0xb9, 0x7f, 0x59, 0xf9, 0xa1, 0x7f, 0x77, 0xf9, 0x4d, 0x2f,
+ 0x3c, 0x1c, 0x52, 0xbf, 0xe6, 0x13, 0x0d, 0xff, 0x69, 0xdd, 0x6e, 0xd0, 0x4b, 0xab, 0xeb, 0xdf,
+ 0x5a, 0x19, 0xf5, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xd6, 0xf4, 0xb6, 0x47, 0x63, 0x25, 0x01,
+ 0x00,
}
func (m *APIServerLogging) Marshal() (dAtA []byte, err error) {
@@ -15942,6 +15943,13 @@ func (m *SeedSettingLoadBalancerServices) MarshalToSizedBuffer(dAtA []byte) (int
_ = i
var l int
_ = l
+ if m.Class != nil {
+ i -= len(*m.Class)
+ copy(dAtA[i:], *m.Class)
+ i = encodeVarintGenerated(dAtA, i, uint64(len(*m.Class)))
+ i--
+ dAtA[i] = 0x32
+ }
if m.ZonalIngress != nil {
{
size, err := m.ZonalIngress.MarshalToSizedBuffer(dAtA[:i])
@@ -22596,6 +22604,10 @@ func (m *SeedSettingLoadBalancerServices) Size() (n int) {
l = m.ZonalIngress.Size()
n += 1 + l + sovGenerated(uint64(l))
}
+ if m.Class != nil {
+ l = len(*m.Class)
+ n += 1 + l + sovGenerated(uint64(l))
+ }
return n
}
@@ -26130,6 +26142,7 @@ func (this *SeedSettingLoadBalancerServices) String() string {
`Zones:` + repeatedStringForZones + `,`,
`ProxyProtocol:` + strings.Replace(this.ProxyProtocol.String(), "LoadBalancerServicesProxyProtocol", "LoadBalancerServicesProxyProtocol", 1) + `,`,
`ZonalIngress:` + strings.Replace(this.ZonalIngress.String(), "SeedSettingLoadBalancerServicesZonalIngress", "SeedSettingLoadBalancerServicesZonalIngress", 1) + `,`,
+ `Class:` + valueToStringGenerated(this.Class) + `,`,
`}`,
}, "")
return s
@@ -53844,6 +53857,39 @@ func (m *SeedSettingLoadBalancerServices) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Class", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenerated
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthGenerated
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthGenerated
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ s := string(dAtA[iNdEx:postIndex])
+ m.Class = &s
+ iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
diff --git a/pkg/apis/core/v1beta1/generated.proto b/pkg/apis/core/v1beta1/generated.proto
index 1e397da85de..658e7768912 100644
--- a/pkg/apis/core/v1beta1/generated.proto
+++ b/pkg/apis/core/v1beta1/generated.proto
@@ -2850,6 +2850,11 @@ message SeedSettingLoadBalancerServices {
// Defaults to true.
// +optional
optional SeedSettingLoadBalancerServicesZonalIngress zonalIngress = 5;
+
+ // Class configures the Service.spec.loadBalancerClass field for the load balancer services on the seed.
+ // Note that changing the loadBalancerClass of existing LoadBalancer services is denied by Kubernetes.
+ // +optional
+ optional string class = 6;
}
// SeedSettingLoadBalancerServicesZonalIngress controls the deployment of ingress gateways per availability zone.
diff --git a/pkg/apis/core/v1beta1/types_seed.go b/pkg/apis/core/v1beta1/types_seed.go
index f185a1e59e6..647b8964d9f 100644
--- a/pkg/apis/core/v1beta1/types_seed.go
+++ b/pkg/apis/core/v1beta1/types_seed.go
@@ -347,6 +347,10 @@ type SeedSettingLoadBalancerServices struct {
// Defaults to true.
// +optional
ZonalIngress *SeedSettingLoadBalancerServicesZonalIngress `json:"zonalIngress,omitempty" protobuf:"bytes,5,opt,name=zonalIngress"`
+ // Class configures the Service.spec.loadBalancerClass field for the load balancer services on the seed.
+ // Note that changing the loadBalancerClass of existing LoadBalancer services is denied by Kubernetes.
+ // +optional
+ Class *string `json:"class,omitempty" protobuf:"bytes,6,opt,name=class"`
}
// SeedSettingLoadBalancerServicesZones controls settings, which are specific to the single-zone load balancers in a
diff --git a/pkg/apis/core/v1beta1/zz_generated.conversion.go b/pkg/apis/core/v1beta1/zz_generated.conversion.go
index e7aa9f0f336..1db27e77ee2 100644
--- a/pkg/apis/core/v1beta1/zz_generated.conversion.go
+++ b/pkg/apis/core/v1beta1/zz_generated.conversion.go
@@ -6270,6 +6270,7 @@ func autoConvert_v1beta1_SeedSettingLoadBalancerServices_To_core_SeedSettingLoad
out.Zones = *(*[]core.SeedSettingLoadBalancerServicesZones)(unsafe.Pointer(&in.Zones))
out.ProxyProtocol = (*core.LoadBalancerServicesProxyProtocol)(unsafe.Pointer(in.ProxyProtocol))
out.ZonalIngress = (*core.SeedSettingLoadBalancerServicesZonalIngress)(unsafe.Pointer(in.ZonalIngress))
+ out.Class = (*string)(unsafe.Pointer(in.Class))
return nil
}
@@ -6284,6 +6285,7 @@ func autoConvert_core_SeedSettingLoadBalancerServices_To_v1beta1_SeedSettingLoad
out.Zones = *(*[]SeedSettingLoadBalancerServicesZones)(unsafe.Pointer(&in.Zones))
out.ProxyProtocol = (*LoadBalancerServicesProxyProtocol)(unsafe.Pointer(in.ProxyProtocol))
out.ZonalIngress = (*SeedSettingLoadBalancerServicesZonalIngress)(unsafe.Pointer(in.ZonalIngress))
+ out.Class = (*string)(unsafe.Pointer(in.Class))
return nil
}
diff --git a/pkg/apis/core/v1beta1/zz_generated.deepcopy.go b/pkg/apis/core/v1beta1/zz_generated.deepcopy.go
index bb6815fd427..5cfe903594a 100644
--- a/pkg/apis/core/v1beta1/zz_generated.deepcopy.go
+++ b/pkg/apis/core/v1beta1/zz_generated.deepcopy.go
@@ -4925,6 +4925,11 @@ func (in *SeedSettingLoadBalancerServices) DeepCopyInto(out *SeedSettingLoadBala
*out = new(SeedSettingLoadBalancerServicesZonalIngress)
(*in).DeepCopyInto(*out)
}
+ if in.Class != nil {
+ in, out := &in.Class, &out.Class
+ *out = new(string)
+ **out = **in
+ }
return
}
diff --git a/pkg/apis/core/validation/seed.go b/pkg/apis/core/validation/seed.go
index c80e708943a..9495f9faf3c 100644
--- a/pkg/apis/core/validation/seed.go
+++ b/pkg/apis/core/validation/seed.go
@@ -158,6 +158,10 @@ func ValidateSeedSpec(seedSpec *core.SeedSpec, fldPath *field.Path, inTemplate b
if seedSpec.Settings.LoadBalancerServices != nil {
allErrs = append(allErrs, apivalidation.ValidateAnnotations(seedSpec.Settings.LoadBalancerServices.Annotations, fldPath.Child("settings", "loadBalancerServices", "annotations"))...)
+ if class := seedSpec.Settings.LoadBalancerServices.Class; class != nil {
+ allErrs = append(allErrs, kubernetescorevalidation.ValidateQualifiedName(*class, fldPath.Child("settings", "loadBalancerServices", "class"))...)
+ }
+
if policy := seedSpec.Settings.LoadBalancerServices.ExternalTrafficPolicy; policy != nil && !availableExternalTrafficPolicies.Has(string(*policy)) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("settings", "loadBalancerServices", "externalTrafficPolicy"), *policy, sets.List(availableExternalTrafficPolicies)))
}
diff --git a/pkg/apis/core/validation/seed_test.go b/pkg/apis/core/validation/seed_test.go
index c8f05f6416e..b8ca21de21e 100644
--- a/pkg/apis/core/validation/seed_test.go
+++ b/pkg/apis/core/validation/seed_test.go
@@ -1320,6 +1320,56 @@ var _ = Describe("Seed Validation Tests", func() {
})),
))
})
+
+ Describe("LoadBalancer class", func() {
+ BeforeEach(func() {
+ seed.Spec.Settings = &core.SeedSettings{
+ LoadBalancerServices: &core.SeedSettingLoadBalancerServices{},
+ }
+ })
+
+ It("should allow omitting the class", func() {
+ seed.Spec.Settings.LoadBalancerServices.Class = nil
+
+ Expect(ValidateSeed(seed)).To(BeEmpty())
+ })
+
+ It("should allow specifying a non-empty class", func() {
+ seed.Spec.Settings.LoadBalancerServices.Class = ptr.To("non-default")
+
+ Expect(ValidateSeed(seed)).To(BeEmpty())
+ })
+
+ It("should allow specifying a qualified class", func() {
+ seed.Spec.Settings.LoadBalancerServices.Class = ptr.To("stackit.cloud/yawol")
+
+ Expect(ValidateSeed(seed)).To(BeEmpty())
+ })
+
+ It("should deny specifying an empty class", func() {
+ seed.Spec.Settings.LoadBalancerServices.Class = ptr.To("")
+
+ Expect(ValidateSeed(seed)).To(ContainElement(
+ PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.settings.loadBalancerServices.class"),
+ "Origin": Equal("format=qualified-name"),
+ })),
+ ))
+ })
+
+ It("should deny specifying a class that Kubernetes does not accept", func() {
+ seed.Spec.Settings.LoadBalancerServices.Class = ptr.To(".invalid-")
+
+ Expect(ValidateSeed(seed)).To(ContainElement(
+ PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.settings.loadBalancerServices.class"),
+ "Origin": Equal("format=qualified-name"),
+ })),
+ ))
+ })
+ })
})
Context("vertical pod autoscaler", func() {
diff --git a/pkg/apis/core/zz_generated.deepcopy.go b/pkg/apis/core/zz_generated.deepcopy.go
index 4c0893d3504..7648fb2f518 100644
--- a/pkg/apis/core/zz_generated.deepcopy.go
+++ b/pkg/apis/core/zz_generated.deepcopy.go
@@ -4925,6 +4925,11 @@ func (in *SeedSettingLoadBalancerServices) DeepCopyInto(out *SeedSettingLoadBala
*out = new(SeedSettingLoadBalancerServicesZonalIngress)
(*in).DeepCopyInto(*out)
}
+ if in.Class != nil {
+ in, out := &in.Class, &out.Class
+ *out = new(string)
+ **out = **in
+ }
return
}
diff --git a/pkg/apiserver/openapi/openapi_generated.go b/pkg/apiserver/openapi/openapi_generated.go
index da3d893769c..f3848af0412 100644
--- a/pkg/apiserver/openapi/openapi_generated.go
+++ b/pkg/apiserver/openapi/openapi_generated.go
@@ -8440,6 +8440,13 @@ func schema_pkg_apis_core_v1beta1_SeedSettingLoadBalancerServices(ref common.Ref
Ref: ref("github.com/gardener/gardener/pkg/apis/core/v1beta1.SeedSettingLoadBalancerServicesZonalIngress"),
},
},
+ "class": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Class configures the Service.spec.loadBalancerClass field for the load balancer services on the seed. Note that changing the loadBalancerClass of existing LoadBalancer services is denied by Kubernetes.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
},
},
},
diff --git a/pkg/component/networking/istio/charts/istio/istio-ingress/templates/service.yaml b/pkg/component/networking/istio/charts/istio/istio-ingress/templates/service.yaml
index 541e1a13b1b..586d020f59c 100644
--- a/pkg/component/networking/istio/charts/istio/istio-ingress/templates/service.yaml
+++ b/pkg/component/networking/istio/charts/istio/istio-ingress/templates/service.yaml
@@ -25,6 +25,9 @@ spec:
{{- if .Values.loadBalancerIP }}
loadBalancerIP: {{ .Values.loadBalancerIP }}
{{- end }}
+{{- with .Values.loadBalancerClass }}
+ loadBalancerClass: {{ . | quote }}
+{{- end }}
{{- if .Values.externalTrafficPolicy }}
externalTrafficPolicy: {{ .Values.externalTrafficPolicy }}
{{- end }}
diff --git a/pkg/component/networking/istio/charts/istio/istio-ingress/values.yaml b/pkg/component/networking/istio/charts/istio/istio-ingress/values.yaml
index ae8bf5b1510..048a36ef74f 100644
--- a/pkg/component/networking/istio/charts/istio/istio-ingress/values.yaml
+++ b/pkg/component/networking/istio/charts/istio/istio-ingress/values.yaml
@@ -22,6 +22,7 @@ ports: []
serviceName: istio-ingressgateway
internalServiceName: istio-ingressgateway-internal
ingressVersion: "1.27.1"
+#loadBalancerClass: non-default-loadbalancer-class
#externalTrafficPolicy: Cluster
replicas: 2
cpuRequests: 300m
diff --git a/pkg/component/networking/istio/ingress_gateway.go b/pkg/component/networking/istio/ingress_gateway.go
index 62f86edb8cf..d86ec9a4051 100644
--- a/pkg/component/networking/istio/ingress_gateway.go
+++ b/pkg/component/networking/istio/ingress_gateway.go
@@ -35,6 +35,7 @@ type IngressGatewayValues struct {
Annotations map[string]string
Labels map[string]string
NetworkPolicyLabels map[string]string
+ LoadBalancerClass *string
ExternalTrafficPolicy *corev1.ServiceExternalTrafficPolicy
Image string
IstiodNamespace string
@@ -104,6 +105,7 @@ func (i *istiod) generateIstioIngressGatewayChart(ctx context.Context) (*chartre
"labels": istioIngressGateway.Labels,
"networkPolicyLabels": istioIngressGateway.NetworkPolicyLabels,
"annotations": istioIngressGateway.Annotations,
+ "loadBalancerClass": istioIngressGateway.LoadBalancerClass,
"externalTrafficPolicy": istioIngressGateway.ExternalTrafficPolicy,
"dualStack": istioIngressGateway.DualStack,
"deployNamespace": false,
diff --git a/pkg/component/networking/istio/istio_test.go b/pkg/component/networking/istio/istio_test.go
index 5715e30ae27..a877a7f25b7 100644
--- a/pkg/component/networking/istio/istio_test.go
+++ b/pkg/component/networking/istio/istio_test.go
@@ -191,6 +191,11 @@ var _ = Describe("istiod", func() {
return string(data)
}
+ istioIngressServiceClass = func() string {
+ data, _ := os.ReadFile("./test_charts/ingress_service_class.yaml")
+ return string(data)
+ }
+
istioIngressServiceETPCluster = func() string {
data, _ := os.ReadFile("./test_charts/ingress_service_etp_cluster.yaml")
return string(data)
@@ -552,6 +557,36 @@ var _ = Describe("istiod", func() {
})
})
+ Context("LoadBalancer class", func() {
+ BeforeEach(func() {
+ igw[0].LoadBalancerClass = ptr.To("non-default-loadbalancer-class")
+ istiod = NewIstio(
+ c,
+ renderer,
+ Values{
+ Istiod: IstiodValues{
+ Enabled: true,
+ Image: "foo/bar",
+ Namespace: deployNS,
+ TrustDomain: "foo.local",
+ Zones: []string{"a", "b", "c"},
+ },
+ IngressGateway: igw,
+ },
+ )
+ })
+
+ It("should successfully deploy correct loadBalancerClass", func() {
+ Expect(c.Get(ctx, client.ObjectKeyFromObject(managedResourceIstioSecret), managedResourceIstioSecret)).To(Succeed())
+
+ var err error
+ istioManifests, err := test.ExtractManifestsFromManagedResourceData(managedResourceIstioSecret.Data)
+ Expect(err).NotTo(HaveOccurred())
+
+ Expect(istioManifests).To(ContainElement(istioIngressServiceClass()))
+ })
+ })
+
Context("external traffic policy cluster", func() {
BeforeEach(func() {
externalTrafficPolicy = corev1.ServiceExternalTrafficPolicyCluster
diff --git a/pkg/component/networking/istio/test_charts/ingress_service_class.yaml b/pkg/component/networking/istio/test_charts/ingress_service_class.yaml
new file mode 100644
index 00000000000..9e388d229b1
--- /dev/null
+++ b/pkg/component/networking/istio/test_charts/ingress_service_class.yaml
@@ -0,0 +1,25 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: istio-ingressgateway
+ namespace: test-ingress
+ annotations:
+ networking.resources.gardener.cloud/from-world-to-ports: '[{"port":8132,"protocol":"TCP"},{"port":8443,"protocol":"TCP"},{"port":9443,"protocol":"TCP"}]'
+ networking.resources.gardener.cloud/namespace-selectors: '[{"matchLabels":{"gardener.cloud/role":"extension"}},{"matchLabels":{"gardener.cloud/role":"shoot"}},{"matchLabels":{"kubernetes.io/metadata.name":"garden"}}]'
+ networking.resources.gardener.cloud/pod-label-selector-namespace-alias: all-istio-ingresses
+ networking.resources.gardener.cloud/from-all-seed-scrape-targets-allowed-ports: '[{"port":15022,"protocol":"TCP"}]'
+ foo: bar
+ labels:
+ app.kubernetes.io/version: 1.27.1
+ app: istio-ingressgateway
+ foo: bar
+spec:
+ type: LoadBalancer
+ selector:
+ app: istio-ingressgateway
+ foo: bar
+ ports:
+ - name: foo
+ port: 999
+ targetPort: 999
+ loadBalancerClass: "non-default-loadbalancer-class"
diff --git a/pkg/component/shared/istio.go b/pkg/component/shared/istio.go
index e60d4572e4a..b3dd8b39c95 100644
--- a/pkg/component/shared/istio.go
+++ b/pkg/component/shared/istio.go
@@ -44,6 +44,7 @@ func NewIstio(
labels map[string]string,
toKubeAPIServerPolicyLabel string,
lbAnnotations map[string]string,
+ loadBalancerClass *string,
externalTrafficPolicy *corev1.ServiceExternalTrafficPolicy,
serviceExternalIP *string,
servicePorts []corev1.ServicePort,
@@ -98,6 +99,7 @@ func NewIstio(
Image: igwImage.String(),
IstiodNamespace: v1beta1constants.IstioSystemNamespace,
Annotations: lbAnnotations,
+ LoadBalancerClass: loadBalancerClass,
ExternalTrafficPolicy: externalTrafficPolicy,
MinReplicas: minReplicas,
MaxReplicas: maxReplicas,
@@ -145,6 +147,7 @@ func AddIstioIngressGateway(
namespace string,
annotations map[string]string,
labels map[string]string,
+ loadBalancerClass *string,
externalTrafficPolicy *corev1.ServiceExternalTrafficPolicy,
serviceExternalIP *string,
zone *string,
@@ -188,6 +191,7 @@ func AddIstioIngressGateway(
Namespace: namespace,
MinReplicas: minReplicas,
MaxReplicas: maxReplicas,
+ LoadBalancerClass: loadBalancerClass,
ExternalTrafficPolicy: externalTrafficPolicy,
LoadBalancerIP: serviceExternalIP,
Image: templateValues.Image,
diff --git a/pkg/component/shared/istio_test.go b/pkg/component/shared/istio_test.go
index c83244eba31..2ac77db6b8c 100644
--- a/pkg/component/shared/istio_test.go
+++ b/pkg/component/shared/istio_test.go
@@ -39,6 +39,7 @@ type istioTestValues struct {
labels map[string]string
kubeAPIServerPolicyLabel string
lbAnnotations map[string]string
+ loadBalancerClass *string
externalTrafficPolicy *corev1.ServiceExternalTrafficPolicy
serviceExternalIP *string
servicePorts []corev1.ServicePort
@@ -70,6 +71,7 @@ func createIstio(testValues istioTestValues) istio.Interface {
testValues.labels,
testValues.kubeAPIServerPolicyLabel,
testValues.lbAnnotations,
+ testValues.loadBalancerClass,
testValues.externalTrafficPolicy,
testValues.serviceExternalIP,
testValues.servicePorts,
@@ -121,6 +123,7 @@ func checkIstio(istioDeploy istio.Interface, testValues istioTestValues) {
Image: testValues.ingressImageName,
IstiodNamespace: "istio-system",
Annotations: testValues.lbAnnotations,
+ LoadBalancerClass: testValues.loadBalancerClass,
ExternalTrafficPolicy: testValues.externalTrafficPolicy,
MinReplicas: minReplicas,
MaxReplicas: maxReplicas,
@@ -145,6 +148,7 @@ func checkAdditionalIstioGateway(cl client.Client,
namespace string,
annotations map[string]string,
labels map[string]string,
+ loadBalancerClass *string,
externalTrafficPolicy *corev1.ServiceExternalTrafficPolicy,
serviceExternalIP *string,
zone *string,
@@ -174,6 +178,7 @@ func checkAdditionalIstioGateway(cl client.Client,
Image: ingressValues[0].Image,
IstiodNamespace: "istio-system",
Annotations: annotations,
+ LoadBalancerClass: loadBalancerClass,
ExternalTrafficPolicy: externalTrafficPolicy,
MinReplicas: minReplicas,
MaxReplicas: maxReplicas,
@@ -219,6 +224,7 @@ var _ = Describe("Istio", func() {
labels: map[string]string{"some": "labelValue"},
kubeAPIServerPolicyLabel: "to-all-test-kube-apiserver",
lbAnnotations: map[string]string{"some": "annotationValue"},
+ loadBalancerClass: ptr.To("non-default-load-balancer-class"),
externalTrafficPolicy: &trafficPolicy,
serviceExternalIP: ptr.To("1.2.3.4"),
servicePorts: []corev1.ServicePort{{Port: 443}},
@@ -317,6 +323,7 @@ var _ = Describe("Istio", func() {
namespace string
annotations map[string]string
labels map[string]string
+ loadBalancerClass *string
externalTrafficPolicy corev1.ServiceExternalTrafficPolicy
serviceExternalIP *string
zone *string
@@ -330,6 +337,7 @@ var _ = Describe("Istio", func() {
labels = map[string]string{
"additional": "istio-ingress-label",
}
+ loadBalancerClass = ptr.To("non-default-load-balancer-class")
externalTrafficPolicy = corev1.ServiceExternalTrafficPolicyCluster
serviceExternalIP = ptr.To("1.1.1.1")
})
@@ -344,6 +352,7 @@ var _ = Describe("Istio", func() {
namespace,
annotations,
labels,
+ loadBalancerClass,
&externalTrafficPolicy,
serviceExternalIP,
zone,
@@ -365,6 +374,7 @@ var _ = Describe("Istio", func() {
namespace,
annotations,
labels,
+ loadBalancerClass,
&externalTrafficPolicy,
serviceExternalIP,
zone,
@@ -378,6 +388,7 @@ var _ = Describe("Istio", func() {
namespace,
annotations,
labels,
+ loadBalancerClass,
&externalTrafficPolicy,
serviceExternalIP,
zone,
@@ -399,6 +410,7 @@ var _ = Describe("Istio", func() {
namespace,
annotations,
labels,
+ loadBalancerClass,
&externalTrafficPolicy,
serviceExternalIP,
zone,
@@ -412,6 +424,7 @@ var _ = Describe("Istio", func() {
namespace,
annotations,
labels,
+ loadBalancerClass,
&externalTrafficPolicy,
serviceExternalIP,
zone,
@@ -436,6 +449,7 @@ var _ = Describe("Istio", func() {
namespace,
annotations,
labels,
+ loadBalancerClass,
&externalTrafficPolicy,
serviceExternalIP,
zone,
@@ -449,6 +463,7 @@ var _ = Describe("Istio", func() {
namespace,
annotations,
labels,
+ loadBalancerClass,
&externalTrafficPolicy,
serviceExternalIP,
zone,
@@ -471,6 +486,7 @@ var _ = Describe("Istio", func() {
namespace,
annotations,
labels,
+ loadBalancerClass,
&externalTrafficPolicy,
serviceExternalIP,
zone,
@@ -484,6 +500,7 @@ var _ = Describe("Istio", func() {
namespace,
annotations,
labels,
+ loadBalancerClass,
&externalTrafficPolicy,
serviceExternalIP,
zone,
diff --git a/pkg/gardenlet/apis/config/v1alpha1/types.go b/pkg/gardenlet/apis/config/v1alpha1/types.go
index d75147ced42..0eecac89e33 100644
--- a/pkg/gardenlet/apis/config/v1alpha1/types.go
+++ b/pkg/gardenlet/apis/config/v1alpha1/types.go
@@ -671,6 +671,11 @@ type ExposureClassHandler struct {
type LoadBalancerServiceConfig struct {
// Annotations is a key value map to annotate the underlying load balancer services.
Annotations map[string]string `json:"annotations"`
+ // Class configures the Service.spec.loadBalancerClass field for the load balancer services of the exposure class
+ // handler. This setting in independent from Seed.spec.settings.loadBalancerServices.class.
+ // Note that changing the loadBalancerClass of existing LoadBalancer services is denied by Kubernetes.
+ // +optional
+ Class *string `json:"class,omitempty"`
}
// MonitoringConfig contains settings for the monitoring stack.
diff --git a/pkg/gardenlet/apis/config/v1alpha1/validation/validation.go b/pkg/gardenlet/apis/config/v1alpha1/validation/validation.go
index 9a7e83c192d..b5746b0b21f 100644
--- a/pkg/gardenlet/apis/config/v1alpha1/validation/validation.go
+++ b/pkg/gardenlet/apis/config/v1alpha1/validation/validation.go
@@ -22,6 +22,7 @@ import (
gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/logger"
validationutils "github.com/gardener/gardener/pkg/utils/validation"
+ kubernetescorevalidation "github.com/gardener/gardener/pkg/utils/validation/kubernetes/core"
)
// ValidateGardenletConfiguration validates a GardenletConfiguration object.
@@ -106,20 +107,7 @@ func ValidateGardenletConfiguration(cfg *gardenletconfigv1alpha1.GardenletConfig
}
}
- exposureClassHandlersPath := fldPath.Child("exposureClassHandlers")
- for i, handler := range cfg.ExposureClassHandlers {
- handlerPath := exposureClassHandlersPath.Index(i)
-
- for _, errorMessage := range validation.IsDNS1123Label(handler.Name) {
- allErrs = append(allErrs, field.Invalid(handlerPath.Child("name"), handler.Name, errorMessage))
- }
-
- if handler.SNI != nil && handler.SNI.Ingress != nil && handler.SNI.Ingress.ServiceExternalIP != nil {
- if ip := net.ParseIP(*handler.SNI.Ingress.ServiceExternalIP); ip == nil {
- allErrs = append(allErrs, field.Invalid(handlerPath.Child("sni", "ingress", "serviceExternalIP"), handler.SNI.Ingress.ServiceExternalIP, "external service ip is invalid"))
- }
- }
- }
+ allErrs = append(allErrs, validateExposureClassHandlers(cfg.ExposureClassHandlers, fldPath.Child("exposureClassHandlers"))...)
if nodeTolerationCfg := cfg.NodeToleration; nodeTolerationCfg != nil {
nodeTolerationConfigPath := fldPath.Child("nodeToleration")
@@ -331,3 +319,27 @@ func validateBastionControllerConfiguration(cfg *gardenletconfigv1alpha1.Bastion
return allErrs
}
+
+func validateExposureClassHandlers(handlers []gardenletconfigv1alpha1.ExposureClassHandler, fldPath *field.Path) field.ErrorList {
+ allErrs := field.ErrorList{}
+
+ for i, handler := range handlers {
+ handlerPath := fldPath.Index(i)
+
+ for _, errorMessage := range validation.IsDNS1123Label(handler.Name) {
+ allErrs = append(allErrs, field.Invalid(handlerPath.Child("name"), handler.Name, errorMessage))
+ }
+
+ if class := handler.LoadBalancerService.Class; class != nil {
+ allErrs = append(allErrs, kubernetescorevalidation.ValidateQualifiedName(*class, handlerPath.Child("loadBalancerService", "class"))...)
+ }
+
+ if handler.SNI != nil && handler.SNI.Ingress != nil && handler.SNI.Ingress.ServiceExternalIP != nil {
+ if ip := net.ParseIP(*handler.SNI.Ingress.ServiceExternalIP); ip == nil {
+ allErrs = append(allErrs, field.Invalid(handlerPath.Child("sni", "ingress", "serviceExternalIP"), handler.SNI.Ingress.ServiceExternalIP, "external service ip is invalid"))
+ }
+ }
+ }
+
+ return allErrs
+}
diff --git a/pkg/gardenlet/apis/config/v1alpha1/validation/validation_test.go b/pkg/gardenlet/apis/config/v1alpha1/validation/validation_test.go
index f8859c619e6..12339cc0de5 100644
--- a/pkg/gardenlet/apis/config/v1alpha1/validation/validation_test.go
+++ b/pkg/gardenlet/apis/config/v1alpha1/validation/validation_test.go
@@ -629,6 +629,50 @@ var _ = Describe("GardenletConfiguration", func() {
}))))
})
+ Describe("LoadBalancer class", func() {
+ It("should allow omitting the class", func() {
+ cfg.ExposureClassHandlers[0].LoadBalancerService.Class = nil
+
+ Expect(ValidateGardenletConfiguration(cfg, nil)).To(BeEmpty())
+ })
+
+ It("should allow specifying a non-empty class", func() {
+ cfg.ExposureClassHandlers[0].LoadBalancerService.Class = ptr.To("non-default")
+
+ Expect(ValidateGardenletConfiguration(cfg, nil)).To(BeEmpty())
+ })
+
+ It("should allow specifying a qualified class", func() {
+ cfg.ExposureClassHandlers[0].LoadBalancerService.Class = ptr.To("stackit.cloud/yawol")
+
+ Expect(ValidateGardenletConfiguration(cfg, nil)).To(BeEmpty())
+ })
+
+ It("should deny specifying an empty class", func() {
+ cfg.ExposureClassHandlers[0].LoadBalancerService.Class = ptr.To("")
+
+ Expect(ValidateGardenletConfiguration(cfg, nil)).To(ContainElement(
+ PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("exposureClassHandlers[0].loadBalancerService.class"),
+ "Origin": Equal("format=qualified-name"),
+ })),
+ ))
+ })
+
+ It("should deny specifying a class that Kubernetes does not accept", func() {
+ cfg.ExposureClassHandlers[0].LoadBalancerService.Class = ptr.To(".invalid-")
+
+ Expect(ValidateGardenletConfiguration(cfg, nil)).To(ContainElement(
+ PointTo(MatchFields(IgnoreExtras, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("exposureClassHandlers[0].loadBalancerService.class"),
+ "Origin": Equal("format=qualified-name"),
+ })),
+ ))
+ })
+ })
+
Context("serviceExternalIP", func() {
It("should allow to use an external service ip as loadbalancer ip is valid", func() {
cfg.ExposureClassHandlers[0].SNI.Ingress.ServiceExternalIP = ptr.To("1.1.1.1")
diff --git a/pkg/gardenlet/apis/config/v1alpha1/zz_generated.deepcopy.go b/pkg/gardenlet/apis/config/v1alpha1/zz_generated.deepcopy.go
index 7a2b5a03cab..164179a0c84 100644
--- a/pkg/gardenlet/apis/config/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/gardenlet/apis/config/v1alpha1/zz_generated.deepcopy.go
@@ -690,6 +690,11 @@ func (in *LoadBalancerServiceConfig) DeepCopyInto(out *LoadBalancerServiceConfig
(*out)[key] = val
}
}
+ if in.Class != nil {
+ in, out := &in.Class, &out.Class
+ *out = new(string)
+ **out = **in
+ }
return
}
diff --git a/pkg/gardenlet/controller/seed/seed/components.go b/pkg/gardenlet/controller/seed/seed/components.go
index 07c359d637c..a9da60186aa 100644
--- a/pkg/gardenlet/controller/seed/seed/components.go
+++ b/pkg/gardenlet/controller/seed/seed/components.go
@@ -338,6 +338,7 @@ func (r *Reconciler) newIstio(ctx context.Context, seed *seedpkg.Seed, isGardenC
labels,
gardenerutils.NetworkPolicyLabel(v1beta1constants.LabelNetworkPolicyShootNamespaceAlias+"-"+v1beta1constants.DeploymentNameKubeAPIServer, kubeapiserverconstants.Port),
seed.GetLoadBalancerServiceAnnotations(),
+ seed.GetLoadBalancerServiceClass(),
seed.GetLoadBalancerServiceExternalTrafficPolicy(),
r.Config.SNI.Ingress.ServiceExternalIP,
servicePorts,
@@ -366,6 +367,7 @@ func (r *Reconciler) newIstio(ctx context.Context, seed *seedpkg.Seed, isGardenC
sharedcomponent.GetIstioNamespaceForZone(*r.Config.SNI.Ingress.Namespace, zone),
seed.GetZonalLoadBalancerServiceAnnotations(zone),
sharedcomponent.GetIstioZoneLabels(labels, &zone),
+ seed.GetLoadBalancerServiceClass(),
seed.GetZonalLoadBalancerServiceExternalTrafficPolicy(zone),
nil,
&zone,
@@ -388,6 +390,7 @@ func (r *Reconciler) newIstio(ctx context.Context, seed *seedpkg.Seed, isGardenC
// handler.LoadBalancerService.Annotations must put last to override non-exposure class related keys.
utils.MergeStringMaps(seed.GetLoadBalancerServiceAnnotations(), handler.LoadBalancerService.Annotations),
sharedcomponent.GetIstioZoneLabels(gardenerutils.GetMandatoryExposureClassHandlerSNILabels(handler.SNI.Ingress.Labels, handler.Name), nil),
+ handler.LoadBalancerService.DeepCopy().Class,
seed.GetLoadBalancerServiceExternalTrafficPolicy(),
handler.SNI.Ingress.ServiceExternalIP,
nil,
@@ -410,6 +413,7 @@ func (r *Reconciler) newIstio(ctx context.Context, seed *seedpkg.Seed, isGardenC
// handler.LoadBalancerService.Annotations must put last to override non-exposure class related keys.
utils.MergeStringMaps(seed.GetZonalLoadBalancerServiceAnnotations(zone), handler.LoadBalancerService.Annotations),
sharedcomponent.GetIstioZoneLabels(gardenerutils.GetMandatoryExposureClassHandlerSNILabels(handler.SNI.Ingress.Labels, handler.Name), &zone),
+ handler.LoadBalancerService.DeepCopy().Class,
seed.GetZonalLoadBalancerServiceExternalTrafficPolicy(zone),
nil,
&zone,
diff --git a/pkg/gardenlet/operation/seed/seed.go b/pkg/gardenlet/operation/seed/seed.go
index 294cff49381..2c884039265 100644
--- a/pkg/gardenlet/operation/seed/seed.go
+++ b/pkg/gardenlet/operation/seed/seed.go
@@ -168,6 +168,16 @@ func (s *Seed) GetLoadBalancerServiceAnnotations() map[string]string {
return nil
}
+// GetLoadBalancerServiceClass returns the load balancer class set for the seed if any.
+func (s *Seed) GetLoadBalancerServiceClass() *string {
+ seed := s.GetInfo()
+ if seed.Spec.Settings != nil && seed.Spec.Settings.LoadBalancerServices != nil {
+ // return copy to prevent accidental mutation by components
+ return seed.Spec.Settings.LoadBalancerServices.DeepCopy().Class
+ }
+ return nil
+}
+
// GetLoadBalancerServiceExternalTrafficPolicy indicates the external traffic policy for the seed if any.
func (s *Seed) GetLoadBalancerServiceExternalTrafficPolicy() *corev1.ServiceExternalTrafficPolicy {
seed := s.GetInfo()
diff --git a/pkg/gardenlet/operation/seed/seed_test.go b/pkg/gardenlet/operation/seed/seed_test.go
index 91c152ddebc..50f092c4e01 100644
--- a/pkg/gardenlet/operation/seed/seed_test.go
+++ b/pkg/gardenlet/operation/seed/seed_test.go
@@ -9,6 +9,7 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
+ "k8s.io/utils/ptr"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
. "github.com/gardener/gardener/pkg/gardenlet/operation/seed"
@@ -122,6 +123,47 @@ var _ = Describe("seed", func() {
})
})
+ Describe("#GetLoadBalancerServiceClass", func() {
+ var seed *Seed
+
+ BeforeEach(func() {
+ seed = &Seed{}
+ })
+
+ It("should return a copied class value if specified", func() {
+ class := ptr.To("my-load-balancer-class")
+
+ seed.SetInfo(&gardencorev1beta1.Seed{
+ Spec: gardencorev1beta1.SeedSpec{
+ Settings: &gardencorev1beta1.SeedSettings{
+ LoadBalancerServices: &gardencorev1beta1.SeedSettingLoadBalancerServices{
+ Class: class,
+ },
+ },
+ },
+ })
+
+ Expect(seed.GetLoadBalancerServiceClass()).To(And(
+ HaveValue(Equal("my-load-balancer-class")),
+ Not(BeIdenticalTo(class)),
+ ))
+ })
+
+ It("should return nil if class is unspecified", func() {
+ seed.SetInfo(&gardencorev1beta1.Seed{
+ Spec: gardencorev1beta1.SeedSpec{
+ Settings: &gardencorev1beta1.SeedSettings{
+ LoadBalancerServices: &gardencorev1beta1.SeedSettingLoadBalancerServices{
+ Class: nil,
+ },
+ },
+ },
+ })
+
+ Expect(seed.GetLoadBalancerServiceClass()).To(BeNil())
+ })
+ })
+
Describe("#GetLoadBalancerServiceExternalTrafficPolicy", func() {
It("should return the traffic policy", func() {
var (
diff --git a/pkg/operator/controller/garden/garden/components.go b/pkg/operator/controller/garden/garden/components.go
index 605870a8363..8d63407e946 100644
--- a/pkg/operator/controller/garden/garden/components.go
+++ b/pkg/operator/controller/garden/garden/components.go
@@ -907,6 +907,7 @@ func (r *Reconciler) newIstio(ctx context.Context, garden *operatorv1alpha1.Gard
annotations,
nil,
nil,
+ nil,
[]corev1.ServicePort{
{Name: "tcp", Port: 443, TargetPort: intstr.FromInt32(9443)},
},
diff --git a/pkg/utils/validation/kubernetes/core/validation.go b/pkg/utils/validation/kubernetes/core/validation.go
index e621a760ad6..0b90775c1a1 100644
--- a/pkg/utils/validation/kubernetes/core/validation.go
+++ b/pkg/utils/validation/kubernetes/core/validation.go
@@ -132,3 +132,13 @@ func ValidateResourceQuantityValue(resource string, value resource.Quantity, fld
return allErrs
}
+
+// ValidateQualifiedName validates if value is what Kubernetes calls a "qualified name".
+// See https://github.com/kubernetes/kubernetes/blob/v1.34.0/pkg/apis/core/validation/validation.go#L144-L151
+func ValidateQualifiedName(value string, fldPath *field.Path) field.ErrorList {
+ allErrs := field.ErrorList{}
+ for _, msg := range validation.IsQualifiedName(value) {
+ allErrs = append(allErrs, field.Invalid(fldPath, value, msg).WithOrigin("format=qualified-name"))
+ }
+ return allErrs
+}
diff --git a/pkg/utils/validation/kubernetes/core/validation_test.go b/pkg/utils/validation/kubernetes/core/validation_test.go
index cfdf5730b5e..ad2db9bb223 100644
--- a/pkg/utils/validation/kubernetes/core/validation_test.go
+++ b/pkg/utils/validation/kubernetes/core/validation_test.go
@@ -20,6 +20,8 @@ limitations under the License.
package core_test
import (
+ "strings"
+
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gstruct"
@@ -153,4 +155,20 @@ var _ = Describe("Validation", func() {
"Field": Equal("resourceQuantity"),
"Detail": Equal("must be an integer"),
})))))
+
+ DescribeTable("#ValidateQualifiedName",
+ func(name string, errMatcher types.GomegaMatcher) {
+ Expect(ValidateQualifiedName(name, field.NewPath("qualifiedName"))).To(errMatcher)
+ },
+
+ Entry("valid qualified name (simple)", "my-name", BeEmpty()),
+ Entry("valid qualified name (with dot)", "my.name", BeEmpty()),
+ Entry("valid qualified name (with dash)", "my-name.test", BeEmpty()),
+ Entry("valid qualified name (max length)", strings.Repeat("a", 63), BeEmpty()),
+ Entry("invalid qualified name (too long)", strings.Repeat("a", 64), Not(BeEmpty())),
+ Entry("invalid qualified name (invalid char)", "my-name[0]", Not(BeEmpty())),
+ Entry("invalid qualified name (starts with dot)", ".myname", Not(BeEmpty())),
+ Entry("invalid qualified name (ends with dash)", "myname-", Not(BeEmpty())),
+ Entry("invalid qualified name (empty)", "", Not(BeEmpty())),
+ )
})
From 14928a127ad188f63e7861111ae7d41e2742a192 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Fri, 7 Nov 2025 14:51:30 +0100
Subject: [PATCH 056/176] Update quay.io/prometheus/alertmanager Docker tag to
v0.29.0 (#13350)
---
imagevector/containers.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index acfef962dc2..54e1df5d6d3 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -227,7 +227,7 @@ images:
- name: alertmanager
sourceRepository: github.com/prometheus/alertmanager
repository: quay.io/prometheus/alertmanager
- tag: v0.28.1
+ tag: v0.29.0
labels:
- name: gardener.cloud/cve-categorisation
value:
From 68129d955a8abfd29a18263c4d809f477dd37c12 Mon Sep 17 00:00:00 2001
From: Dominik Froehlich
Date: Fri, 7 Nov 2025 16:32:23 +0100
Subject: [PATCH 057/176] feat: add readiness probe to vpn tunnel-controller
(#13366)
---
pkg/component/networking/vpn/shoot/shoot.go | 13 +++++++++++++
pkg/component/networking/vpn/shoot/shoot_test.go | 13 +++++++++++++
2 files changed, 26 insertions(+)
diff --git a/pkg/component/networking/vpn/shoot/shoot.go b/pkg/component/networking/vpn/shoot/shoot.go
index ade0f6c9d54..d92d30b0173 100644
--- a/pkg/component/networking/vpn/shoot/shoot.go
+++ b/pkg/component/networking/vpn/shoot/shoot.go
@@ -667,6 +667,19 @@ func (v *vpnShoot) tunnelControllerContainer() *corev1.Container {
Add: []corev1.Capability{"NET_ADMIN"},
},
},
+ ReadinessProbe: &corev1.Probe{
+ ProbeHandler: corev1.ProbeHandler{
+ HTTPGet: &corev1.HTTPGetAction{
+ Path: "/readyz",
+ Port: intstr.FromInt32(8080),
+ },
+ },
+ SuccessThreshold: 2, // Check twice to buy enough time to establish more than one kube apiserver route.
+ FailureThreshold: 1,
+ InitialDelaySeconds: 5,
+ PeriodSeconds: 5,
+ TimeoutSeconds: 2,
+ },
}
}
diff --git a/pkg/component/networking/vpn/shoot/shoot_test.go b/pkg/component/networking/vpn/shoot/shoot_test.go
index d6cf28623ea..50c57bd063b 100644
--- a/pkg/component/networking/vpn/shoot/shoot_test.go
+++ b/pkg/component/networking/vpn/shoot/shoot_test.go
@@ -706,6 +706,19 @@ var _ = Describe("VPNShoot", func() {
},
},
ImagePullPolicy: corev1.PullIfNotPresent,
+ ReadinessProbe: &corev1.Probe{
+ ProbeHandler: corev1.ProbeHandler{
+ HTTPGet: &corev1.HTTPGetAction{
+ Path: "/readyz",
+ Port: intstr.FromInt32(8080),
+ },
+ },
+ SuccessThreshold: 2,
+ FailureThreshold: 1,
+ InitialDelaySeconds: 5,
+ PeriodSeconds: 5,
+ TimeoutSeconds: 2,
+ },
})
}
From 615272edec336264ba884d80594b23d40b6540e9 Mon Sep 17 00:00:00 2001
From: Sebastian Stauch
Date: Fri, 7 Nov 2025 16:32:30 +0100
Subject: [PATCH 058/176] Reapply server block imports (#13375)
* Reapply "support server block imports for node-local-dns (#13160)" (#13344)
This reverts commit f34fc0bfb2d272d02d2afbb0dc24d25c74a2a33f.
* update image tage of coredns-config-adapter to v0.4.0
* update documentation
---
docs/usage/networking/custom-dns-config.md | 6 +-
docs/usage/networking/node-local-dns.md | 2 +-
imagevector/containers.go | 2 +
imagevector/containers.yaml | 17 +++++
pkg/component/networking/coredns/coredns.go | 5 +-
.../networking/nodelocaldns/nodelocaldns.go | 19 +++---
.../nodelocaldns/nodelocaldns_test.go | 53 +++++++++++++++-
.../networking/nodelocaldns/resources.go | 63 +++++++++++++++++--
.../operation/botanist/nodelocaldns.go | 20 +++---
.../controller/dnsrecord/actuator.go | 3 +-
.../controller/dnsrecord/actuator_test.go | 5 +-
skaffold-gardenadm.yaml | 2 +
skaffold-operator.yaml | 2 +
skaffold.yaml | 2 +
14 files changed, 173 insertions(+), 28 deletions(-)
diff --git a/docs/usage/networking/custom-dns-config.md b/docs/usage/networking/custom-dns-config.md
index 706f162f69c..fef710d0b2e 100644
--- a/docs/usage/networking/custom-dns-config.md
+++ b/docs/usage/networking/custom-dns-config.md
@@ -102,9 +102,9 @@ This should bring the cluster DNS back to functioning state.
## Node Local DNS
-Starting with Gardener v1.128, custom DNS configurations are fully supported in NodeLocalDNS. In this version, the `coredns-custom` `ConfigMap` is mounted into the NodeLocalDNS pod, allowing custom override and server configurations to be imported into the DNS server. Prior to Gardener v1.128, custom DNS configurations might not function as expected with NodeLocalDNS.
-With NodeLocalDNS, ordinary DNS queries targeting upstream DNS servers (i.e., non-Kubernetes domains) are sent directly to the upstream DNS server, bypassing CoreDNS. Therefore, configurations for non-Kubernetes entities, such as the `istio.server` block in the [custom DNS configuration](custom-dns-config.md) example, may not have any effect when NodeLocalDNS is enabled on landscapes with Gardener prior to v1.128.
-If you require custom DNS configurations for non-Kubernetes domains, you need to disable forwarding to upstream DNS with Gardener v1.127 and below. This can be done by setting the `disableForwardToUpstreamDNS` option in the Shoot resource to `true`:
+Starting with Gardener v1.132, custom DNS configurations are fully supported in NodeLocalDNS. In this version, the `coredns-custom` `ConfigMap` is mounted into the NodeLocalDNS pod, allowing custom override and server configurations to be imported into the DNS server. The server configuration is read by a sidecar container and a new configuration file with the correct bind statement and port mappings is generated and imported into NodeLocalDNS pods. Prior to Gardener v1.132, custom DNS configurations might not function as expected with NodeLocalDNS.
+With NodeLocalDNS, ordinary DNS queries targeting upstream DNS servers (i.e., non-Kubernetes domains) are sent directly to the upstream DNS server, bypassing CoreDNS. Therefore, configurations for non-Kubernetes entities, such as the `istio.server` block in the [custom DNS configuration](custom-dns-config.md) example, may not have any effect when NodeLocalDNS is enabled on landscapes with Gardener prior to v1.132.
+If you require custom DNS configurations for non-Kubernetes domains, you need to disable forwarding to upstream DNS with Gardener v1.131 and below. This can be done by setting the `disableForwardToUpstreamDNS` option in the Shoot resource to `true`:
```yaml
...
spec:
diff --git a/docs/usage/networking/node-local-dns.md b/docs/usage/networking/node-local-dns.md
index ca95fa01af6..a83340e572f 100644
--- a/docs/usage/networking/node-local-dns.md
+++ b/docs/usage/networking/node-local-dns.md
@@ -48,5 +48,5 @@ For more information about `node-local-dns`, please refer to the [KEP](https://g
## Known Issues
-Custom DNS configuration may not work as expected in conjunction with `NodeLocalDNS` prior to gardener v1.128.
+Custom DNS configuration may not work as expected in conjunction with `NodeLocalDNS` prior to gardener v1.132.
Please refer to [Custom DNS Configuration](custom-dns-config.md#node-local-dns).
diff --git a/imagevector/containers.go b/imagevector/containers.go
index c655a64e28e..0ea93ce1eab 100644
--- a/imagevector/containers.go
+++ b/imagevector/containers.go
@@ -25,6 +25,8 @@ const (
ContainerImageNameConfigmapReloader = "configmap-reloader"
// ContainerImageNameCoredns is a constant for an image in the image vector with name 'coredns'.
ContainerImageNameCoredns = "coredns"
+ // ContainerImageNameCorednsConfigAdapter is a constant for an image in the image vector with name 'coredns-config-adapter'.
+ ContainerImageNameCorednsConfigAdapter = "coredns-config-adapter"
// ContainerImageNameCortex is a constant for an image in the image vector with name 'cortex'.
ContainerImageNameCortex = "cortex"
// ContainerImageNameDependencyWatchdog is a constant for an image in the image vector with name 'dependency-watchdog'.
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index 54e1df5d6d3..2c77224573c 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -494,6 +494,23 @@ images:
value:
- type: 'githubTeam'
teamname: 'gardener/gardener-core-networking-maintainers'
+ - name: coredns-config-adapter
+ sourceRepository: github.com/gardener/coredns-config-adapter
+ repository: europe-docker.pkg.dev/gardener-project/releases/gardener/coredns-config-adapter
+ tag: "v0.4.0"
+ labels:
+ - name: 'gardener.cloud/cve-categorisation'
+ value:
+ network_exposure: 'private'
+ authentication_enforced: false
+ user_interaction: 'end-user'
+ confidentiality_requirement: 'low'
+ integrity_requirement: 'high'
+ availability_requirement: 'high'
+ - name: 'cloud.gardener.cnudie/responsibles'
+ value:
+ - type: 'githubTeam'
+ teamname: 'gardener/gardener-core-networking-maintainers'
- name: node-problem-detector
sourceRepository: github.com/kubernetes/node-problem-detector
repository: registry.k8s.io/node-problem-detector/node-problem-detector
diff --git a/pkg/component/networking/coredns/coredns.go b/pkg/component/networking/coredns/coredns.go
index 68175e44986..e5db3bcaa4a 100644
--- a/pkg/component/networking/coredns/coredns.go
+++ b/pkg/component/networking/coredns/coredns.go
@@ -55,6 +55,9 @@ const (
containerName = "coredns"
serviceName = "kube-dns" // this is due to legacy reasons
+ // CustomConfigMapName is the name of the custom CoreDNS ConfigMap.
+ CustomConfigMapName = "coredns-custom"
+
portNameMetrics = "metrics"
portMetrics = 9153
@@ -319,7 +322,7 @@ import custom/*.server
configMapCustom = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
- Name: "coredns-custom",
+ Name: CustomConfigMapName,
Namespace: metav1.NamespaceSystem,
Annotations: map[string]string{resourcesv1alpha1.Ignore: "true"},
},
diff --git a/pkg/component/networking/nodelocaldns/nodelocaldns.go b/pkg/component/networking/nodelocaldns/nodelocaldns.go
index 571c70e10b5..52891283d63 100644
--- a/pkg/component/networking/nodelocaldns/nodelocaldns.go
+++ b/pkg/component/networking/nodelocaldns/nodelocaldns.go
@@ -64,6 +64,8 @@ const (
metricsPortName = "metrics"
errorMetricsPortName = "errormetrics"
+ sideCarName = "coredns-config-adapter"
+
domain = gardencorev1beta1.DefaultDomain
serviceName = "kube-dns-upstream"
livenessProbePort = 8099
@@ -74,13 +76,14 @@ const (
daemonSetPollInterval = 5 * time.Second
- volumeMountNameCleanUp = "cleanup-script"
- volumeMountPathCleanUp = "/scripts"
- volumeMountNameXtablesLock = "xtables-lock"
- volumeMountPathXtablesLock = "/run/xtables.lock"
- volumeMountPathCustomConfig = "/etc/custom"
- volumeMountNameCustomConfig = "custom-config-volume"
- customConfigMapName = "coredns-custom"
+ volumeMountNameCleanUp = "cleanup-script"
+ volumeMountPathCleanUp = "/scripts"
+ volumeMountNameXtablesLock = "xtables-lock"
+ volumeMountPathXtablesLock = "/run/xtables.lock"
+ volumeMountPathCustomConfig = "/etc/custom"
+ volumeMountNameCustomConfig = "custom-config-volume"
+ volumeMountNameGeneratedConfig = "generated-config"
+ volumeMountPathGeneratedConfig = "/etc/generated-config"
)
var (
@@ -103,6 +106,8 @@ type Values struct {
Image string
// AlpineImage is the container image used for the cleanup DaemonSet.
AlpineImage string
+ // CorednsConfigAdapterImage is the container image used for the coredns config adapter sidecar.
+ CorednsConfigAdapterImage string
// VPAEnabled marks whether VerticalPodAutoscaler is enabled for the shoot.
VPAEnabled bool
// Config is the node local configuration for the shoot spec
diff --git a/pkg/component/networking/nodelocaldns/nodelocaldns_test.go b/pkg/component/networking/nodelocaldns/nodelocaldns_test.go
index 3518128667c..2a0ff6eeed3 100644
--- a/pkg/component/networking/nodelocaldns/nodelocaldns_test.go
+++ b/pkg/component/networking/nodelocaldns/nodelocaldns_test.go
@@ -31,6 +31,7 @@ import (
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
"github.com/gardener/gardener/pkg/client/kubernetes"
"github.com/gardener/gardener/pkg/component"
+ "github.com/gardener/gardener/pkg/component/networking/coredns"
. "github.com/gardener/gardener/pkg/component/networking/nodelocaldns"
"github.com/gardener/gardener/pkg/resourcemanager/controller/garbagecollector/references"
"github.com/gardener/gardener/pkg/utils"
@@ -350,6 +351,7 @@ data:
cache 30
reload
}
+ import generated-config/custom-server-block.server
immutable: true
kind: ConfigMap
metadata:
@@ -451,6 +453,41 @@ status:
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
},
+ InitContainers: []corev1.Container{
+ {
+ Name: "coredns-config-adapter",
+ Image: values.CorednsConfigAdapterImage,
+ Resources: corev1.ResourceRequirements{
+ Requests: corev1.ResourceList{
+ corev1.ResourceCPU: resource.MustParse("5m"),
+ corev1.ResourceMemory: resource.MustParse("10Mi"),
+ },
+ },
+ SecurityContext: &corev1.SecurityContext{
+ AllowPrivilegeEscalation: ptr.To(false),
+ RunAsNonRoot: ptr.To(true),
+ RunAsUser: ptr.To[int64](65532),
+ RunAsGroup: ptr.To[int64](65532),
+ },
+ Args: []string{
+ "-inputDir=/etc/custom",
+ "-outputDir=/etc/generated-config",
+ "-bind=bind " + bindIP(values),
+ },
+ VolumeMounts: []corev1.VolumeMount{
+ {
+ Name: "custom-config-volume",
+ MountPath: "/etc/custom",
+ ReadOnly: true,
+ },
+ {
+ MountPath: "/etc/generated-config",
+ Name: "generated-config",
+ },
+ },
+ RestartPolicy: ptr.To(corev1.ContainerRestartPolicyAlways),
+ },
+ },
Containers: []corev1.Container{
{
Name: "node-cache",
@@ -532,6 +569,10 @@ status:
MountPath: "/etc/custom",
ReadOnly: true,
},
+ {
+ MountPath: "/etc/generated-config",
+ Name: "generated-config",
+ },
},
},
},
@@ -577,13 +618,19 @@ status:
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
- Name: "coredns-custom",
+ Name: coredns.CustomConfigMapName,
},
DefaultMode: ptr.To[int32](420),
Optional: ptr.To(true),
},
},
},
+ {
+ Name: "generated-config",
+ VolumeSource: corev1.VolumeSource{
+ EmptyDir: &corev1.EmptyDirVolumeSource{},
+ },
+ },
},
},
},
@@ -601,6 +648,8 @@ spec:
containerPolicies:
- containerName: '*'
controlledValues: RequestsOnly
+ - containerName: coredns-config-adapter
+ mode: "Off"
targetRef:
apiVersion: apps/v1
kind: DaemonSet
@@ -720,6 +769,7 @@ ip6.arpa:53 {
cache 30
reload
}
+import generated-config/custom-server-block.server
`,
}
configMapHash = utils.ComputeConfigMapChecksum(configMapData)[:8]
@@ -994,6 +1044,7 @@ ip6.arpa:53 {
cache 30
reload
}
+import generated-config/custom-server-block.server
`,
}
configMapHash = utils.ComputeConfigMapChecksum(configMapData)[:8]
diff --git a/pkg/component/networking/nodelocaldns/resources.go b/pkg/component/networking/nodelocaldns/resources.go
index 78fdf7ecd4d..b184a9ef61b 100644
--- a/pkg/component/networking/nodelocaldns/resources.go
+++ b/pkg/component/networking/nodelocaldns/resources.go
@@ -21,6 +21,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ "github.com/gardener/gardener/pkg/component/networking/coredns"
nodelocaldnsconstants "github.com/gardener/gardener/pkg/component/networking/nodelocaldns/constants"
"github.com/gardener/gardener/pkg/resourcemanager/controller/garbagecollector/references"
kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
@@ -100,6 +101,7 @@ ip6.arpa:53 {
cache 30
reload
}
+import generated-config/custom-server-block.server
`,
},
}
@@ -208,6 +210,41 @@ func (n *nodeLocalDNS) computePoolResourcesData(serviceAccount *corev1.ServiceAc
v1beta1constants.LabelNodeLocalDNS: "true",
v1beta1constants.LabelWorkerPool: worker.Name,
},
+ InitContainers: []corev1.Container{
+ {
+ Name: sideCarName,
+ Image: n.values.CorednsConfigAdapterImage,
+ Resources: corev1.ResourceRequirements{
+ Requests: corev1.ResourceList{
+ corev1.ResourceCPU: resource.MustParse("5m"),
+ corev1.ResourceMemory: resource.MustParse("10Mi"),
+ },
+ },
+ SecurityContext: &corev1.SecurityContext{
+ AllowPrivilegeEscalation: ptr.To(false),
+ RunAsNonRoot: ptr.To(true),
+ RunAsUser: ptr.To[int64](65532),
+ RunAsGroup: ptr.To[int64](65532),
+ },
+ Args: []string{
+ "-inputDir=" + volumeMountPathCustomConfig,
+ "-outputDir=" + volumeMountPathGeneratedConfig,
+ "-bind=bind " + n.bindIP(),
+ },
+ VolumeMounts: []corev1.VolumeMount{
+ {
+ Name: volumeMountNameCustomConfig,
+ MountPath: volumeMountPathCustomConfig,
+ ReadOnly: true,
+ },
+ {
+ MountPath: volumeMountPathGeneratedConfig,
+ Name: volumeMountNameGeneratedConfig,
+ },
+ },
+ RestartPolicy: ptr.To(corev1.ContainerRestartPolicyAlways),
+ },
+ },
Containers: []corev1.Container{
{
Name: containerName,
@@ -289,6 +326,10 @@ func (n *nodeLocalDNS) computePoolResourcesData(serviceAccount *corev1.ServiceAc
MountPath: volumeMountPathCustomConfig,
ReadOnly: true,
},
+ {
+ MountPath: volumeMountPathGeneratedConfig,
+ Name: volumeMountNameGeneratedConfig,
+ },
},
},
},
@@ -334,13 +375,19 @@ func (n *nodeLocalDNS) computePoolResourcesData(serviceAccount *corev1.ServiceAc
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
- Name: customConfigMapName,
+ Name: coredns.CustomConfigMapName,
},
DefaultMode: ptr.To[int32](420),
Optional: ptr.To(true),
},
},
},
+ {
+ Name: volumeMountNameGeneratedConfig,
+ VolumeSource: corev1.VolumeSource{
+ EmptyDir: &corev1.EmptyDirVolumeSource{},
+ },
+ },
},
},
},
@@ -366,10 +413,16 @@ func (n *nodeLocalDNS) computePoolResourcesData(serviceAccount *corev1.ServiceAc
UpdateMode: &vpaUpdateMode,
},
ResourcePolicy: &vpaautoscalingv1.PodResourcePolicy{
- ContainerPolicies: []vpaautoscalingv1.ContainerResourcePolicy{{
- ContainerName: vpaautoscalingv1.DefaultContainerResourcePolicy,
- ControlledValues: ptr.To(vpaautoscalingv1.ContainerControlledValuesRequestsOnly),
- }},
+ ContainerPolicies: []vpaautoscalingv1.ContainerResourcePolicy{
+ {
+ ContainerName: vpaautoscalingv1.DefaultContainerResourcePolicy,
+ ControlledValues: ptr.To(vpaautoscalingv1.ContainerControlledValuesRequestsOnly),
+ },
+ {
+ ContainerName: sideCarName,
+ Mode: ptr.To(vpaautoscalingv1.ContainerScalingModeOff),
+ },
+ },
},
},
}
diff --git a/pkg/gardenlet/operation/botanist/nodelocaldns.go b/pkg/gardenlet/operation/botanist/nodelocaldns.go
index f1ab2b75b73..4691d8715e3 100644
--- a/pkg/gardenlet/operation/botanist/nodelocaldns.go
+++ b/pkg/gardenlet/operation/botanist/nodelocaldns.go
@@ -35,17 +35,23 @@ func (b *Botanist) DefaultNodeLocalDNS() (nodelocaldns.Interface, error) {
return nil, err
}
+ imageCorednsConfigAdapter, err := imagevector.Containers().FindImage(imagevector.ContainerImageNameCorednsConfigAdapter)
+ if err != nil {
+ return nil, err
+ }
+
return nodelocaldns.New(
b.SeedClientSet.Client(),
b.Shoot.ControlPlaneNamespace,
nodelocaldns.Values{
- Image: image.String(),
- AlpineImage: imageAlpine.String(),
- VPAEnabled: b.Shoot.WantsVerticalPodAutoscaler,
- Config: v1beta1helper.GetNodeLocalDNS(b.Shoot.GetInfo().Spec.SystemComponents),
- Workers: b.Shoot.GetInfo().Spec.Provider.Workers,
- KubeProxyConfig: b.Shoot.GetInfo().Spec.Kubernetes.KubeProxy,
- Log: b.Logger,
+ Image: image.String(),
+ AlpineImage: imageAlpine.String(),
+ CorednsConfigAdapterImage: imageCorednsConfigAdapter.String(),
+ VPAEnabled: b.Shoot.WantsVerticalPodAutoscaler,
+ Config: v1beta1helper.GetNodeLocalDNS(b.Shoot.GetInfo().Spec.SystemComponents),
+ Workers: b.Shoot.GetInfo().Spec.Provider.Workers,
+ KubeProxyConfig: b.Shoot.GetInfo().Spec.Kubernetes.KubeProxy,
+ Log: b.Logger,
},
), nil
}
diff --git a/pkg/provider-local/controller/dnsrecord/actuator.go b/pkg/provider-local/controller/dnsrecord/actuator.go
index a12611e09d7..905d40f3207 100644
--- a/pkg/provider-local/controller/dnsrecord/actuator.go
+++ b/pkg/provider-local/controller/dnsrecord/actuator.go
@@ -21,6 +21,7 @@ import (
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
+ "github.com/gardener/gardener/pkg/component/networking/coredns"
)
// Actuator implements the DNSRecord actuator for the local DNS provider.
@@ -85,7 +86,7 @@ func (a *Actuator) Restore(ctx context.Context, log logr.Logger, dnsRecord *exte
}
func (a *Actuator) patchCoreDNSConfigMap(ctx context.Context, mutate func(configMap *corev1.ConfigMap)) error {
- configMap := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "coredns-custom", Namespace: "gardener-extension-provider-local-coredns"}}
+ configMap := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: coredns.CustomConfigMapName, Namespace: "gardener-extension-provider-local-coredns"}}
_, err := controllerutil.CreateOrPatch(ctx, a.Client, configMap, func() error {
mutate(configMap)
return nil
diff --git a/pkg/provider-local/controller/dnsrecord/actuator_test.go b/pkg/provider-local/controller/dnsrecord/actuator_test.go
index fe3d9303184..fb6edac999f 100644
--- a/pkg/provider-local/controller/dnsrecord/actuator_test.go
+++ b/pkg/provider-local/controller/dnsrecord/actuator_test.go
@@ -22,6 +22,7 @@ import (
"github.com/gardener/gardener/extensions/pkg/controller/dnsrecord"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
+ "github.com/gardener/gardener/pkg/component/networking/coredns"
"github.com/gardener/gardener/pkg/logger"
. "github.com/gardener/gardener/pkg/provider-local/controller/dnsrecord"
)
@@ -103,14 +104,14 @@ var _ = Describe("Actuator", func() {
}
emptyConfigMap = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
- Name: "coredns-custom",
+ Name: coredns.CustomConfigMapName,
Namespace: extensionNamespace.Name,
},
Data: map[string]string{"test": "data"},
}
configMapWithRule = &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
- Name: "coredns-custom",
+ Name: coredns.CustomConfigMapName,
Namespace: extensionNamespace.Name,
},
Data: map[string]string{
diff --git a/skaffold-gardenadm.yaml b/skaffold-gardenadm.yaml
index fff45bdb73d..63fecc64b89 100644
--- a/skaffold-gardenadm.yaml
+++ b/skaffold-gardenadm.yaml
@@ -1132,6 +1132,8 @@ build:
- pkg/component/kubernetes/proxy
- pkg/component/kubernetes/proxy/resources/cleanup.sh
- pkg/component/kubernetes/proxy/resources/conntrack-fix.sh
+ - pkg/component/networking/coredns
+ - pkg/component/networking/coredns/constants
- pkg/component/nodemanagement/machinecontrollermanager
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml
diff --git a/skaffold-operator.yaml b/skaffold-operator.yaml
index 7f5dfe7f84f..234857b7643 100644
--- a/skaffold-operator.yaml
+++ b/skaffold-operator.yaml
@@ -1146,6 +1146,8 @@ build:
- pkg/component/kubernetes/proxy
- pkg/component/kubernetes/proxy/resources/cleanup.sh
- pkg/component/kubernetes/proxy/resources/conntrack-fix.sh
+ - pkg/component/networking/coredns
+ - pkg/component/networking/coredns/constants
- pkg/component/nodemanagement/machinecontrollermanager
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml
diff --git a/skaffold.yaml b/skaffold.yaml
index 7bde9200a08..1d8c51412d5 100644
--- a/skaffold.yaml
+++ b/skaffold.yaml
@@ -740,6 +740,8 @@ build:
- pkg/component/kubernetes/proxy
- pkg/component/kubernetes/proxy/resources/cleanup.sh
- pkg/component/kubernetes/proxy/resources/conntrack-fix.sh
+ - pkg/component/networking/coredns
+ - pkg/component/networking/coredns/constants
- pkg/component/nodemanagement/machinecontrollermanager
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machineclasses.yaml
- pkg/component/nodemanagement/machinecontrollermanager/templates/crd-machine.sapcloud.io_machinedeployments.yaml
From 6c2ef38f8f8fff59393c7f1d656b1a12007841e6 Mon Sep 17 00:00:00 2001
From: Jeremy Rickards <9338170+rickardsjp@users.noreply.github.com>
Date: Fri, 7 Nov 2025 16:32:39 +0100
Subject: [PATCH 059/176] Stop deploying `cache-node-exporter` ServiceMonitor
on unmanaged `Seed`s (#13382)
Gardener does not deploy the node-exporter DaemonSet on unmanaged seed
clusters, i.e. seed clusters that are not simultaneously also shoot
clusters.
With this change, it also stops deploying the ServiceMonitor in the
`kube-system` namespace that is used by the prometheus-cache to scrape
node-exporter instances on managed seeds.
---
.../monitoring/prometheus/cache/servicemonitors.go | 13 +++++++++----
.../prometheus/cache/servicemonitors_test.go | 8 ++++++--
pkg/gardenlet/controller/seed/seed/components.go | 2 +-
3 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/pkg/component/observability/monitoring/prometheus/cache/servicemonitors.go b/pkg/component/observability/monitoring/prometheus/cache/servicemonitors.go
index 532df2a0a30..b5cac22f417 100644
--- a/pkg/component/observability/monitoring/prometheus/cache/servicemonitors.go
+++ b/pkg/component/observability/monitoring/prometheus/cache/servicemonitors.go
@@ -12,9 +12,12 @@ import (
)
// CentralServiceMonitors returns the central ServiceMonitor resources for the cache prometheus.
-func CentralServiceMonitors() []*monitoringv1.ServiceMonitor {
- return []*monitoringv1.ServiceMonitor{
- {
+func CentralServiceMonitors(seedIsShoot bool) []*monitoringv1.ServiceMonitor {
+ var serviceMonitors []*monitoringv1.ServiceMonitor
+
+ if seedIsShoot {
+ // add cache-node-exporter ServiceMonitor only to ManagedSeeds.
+ serviceMonitors = append(serviceMonitors, &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "node-exporter",
Namespace: metav1.NamespaceSystem,
@@ -53,6 +56,8 @@ func CentralServiceMonitors() []*monitoringv1.ServiceMonitor {
),
}},
},
- },
+ })
}
+
+ return serviceMonitors
}
diff --git a/pkg/component/observability/monitoring/prometheus/cache/servicemonitors_test.go b/pkg/component/observability/monitoring/prometheus/cache/servicemonitors_test.go
index 1b61e1f8078..636101f153b 100644
--- a/pkg/component/observability/monitoring/prometheus/cache/servicemonitors_test.go
+++ b/pkg/component/observability/monitoring/prometheus/cache/servicemonitors_test.go
@@ -16,8 +16,8 @@ import (
var _ = Describe("ServiceMonitors", func() {
Describe("#CentralServiceMonitors", func() {
- It("should return the expected objects", func() {
- Expect(cache.CentralServiceMonitors()).To(HaveExactElements(&monitoringv1.ServiceMonitor{
+ It("should return the service monitors for ManagedSeeds", func() {
+ Expect(cache.CentralServiceMonitors(true)).To(HaveExactElements(&monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "node-exporter",
Namespace: "kube-system",
@@ -58,5 +58,9 @@ var _ = Describe("ServiceMonitors", func() {
},
}))
})
+
+ It("should not return the service monitors for unmanaged Seeds", func() {
+ Expect(cache.CentralServiceMonitors(false)).To(BeEmpty())
+ })
})
})
diff --git a/pkg/gardenlet/controller/seed/seed/components.go b/pkg/gardenlet/controller/seed/seed/components.go
index a9da60186aa..f6df0b2ca97 100644
--- a/pkg/gardenlet/controller/seed/seed/components.go
+++ b/pkg/gardenlet/controller/seed/seed/components.go
@@ -601,7 +601,7 @@ func (r *Reconciler) newCachePrometheus(log logr.Logger, seed *seedpkg.Seed, see
},
CentralConfigs: prometheus.CentralConfigs{
AdditionalScrapeConfigs: additionalScrapeConfigs,
- ServiceMonitors: cacheprometheus.CentralServiceMonitors(),
+ ServiceMonitors: cacheprometheus.CentralServiceMonitors(seedIsShoot),
PrometheusRules: cacheprometheus.CentralPrometheusRules(),
},
AdditionalResources: []client.Object{
From f3e7bc71fcc43484bbc9c5a25ea91e6cb2a53cd2 Mon Sep 17 00:00:00 2001
From: Tim Ebert
Date: Sat, 8 Nov 2025 10:28:26 +0100
Subject: [PATCH 060/176] [GEP-28] `gardenadm init`: Deploy/restore
`Infrastructure` (#13353)
* Document new credentials handling in provider-local
* Add kind kubeconfig to secret of shoot with managed infra
* Use provider client in `Infrastructure` controller
* Side: clean up deletion of no longer existing objects
* `gardenadm init`: Deploy/restore `Infrastructure`
If the shoot's infrastructure is managed by gardener, `gardenadm init` will deploy the `Infrastructure` object into
the self-hosted shoot. It restores the extension state from the `ShootState` compiled by `gardenadm bootstrap` from
the bootstrap cluster.
The shoot networks might only be known after the `Infrastructure` reconciliation, so kube-proxy and `Network`
deployment depend on a successful `Infrastructure` reconciliation.
* Add e2e test coverage
* Rename seedClient to runtimeClient
The wording "runtime client" fits more cases while still being simple enough to understand.
* Address review suggestions
* Rework dev-setup structure as suggested
---
.../overlays/managed-infra/kustomization.yaml | 2 +-
.../.gitignore | 1 +
.../kustomization.yaml | 22 ++++++++++
.../secretbinding.yaml | 9 ++++
docs/extensions/provider-local.md | 9 ++++
hack/kind-up.sh | 7 +++
pkg/gardenadm/cmd/init/init.go | 18 ++++++--
.../controller/infrastructure/actuator.go | 30 +++++++++----
pkg/provider-local/local/client.go | 44 +++++++++++++++++++
test/e2e/gardenadm/managedinfra/gardenadm.go | 23 +++++++++-
10 files changed, 151 insertions(+), 14 deletions(-)
create mode 100644 dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/.gitignore
create mode 100644 dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/kustomization.yaml
create mode 100644 dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/secretbinding.yaml
create mode 100644 pkg/provider-local/local/client.go
diff --git a/dev-setup/gardenadm/resources/overlays/managed-infra/kustomization.yaml b/dev-setup/gardenadm/resources/overlays/managed-infra/kustomization.yaml
index 111f5bf56bc..8a7c4732bf2 100644
--- a/dev-setup/gardenadm/resources/overlays/managed-infra/kustomization.yaml
+++ b/dev-setup/gardenadm/resources/overlays/managed-infra/kustomization.yaml
@@ -8,7 +8,7 @@ resources:
- ../../base
components:
-- ../../../../gardenconfig/components/credentials/secret-project-garden
+- ../../../../gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig
patches:
- path: patch-shoot-managed-infra.yaml
diff --git a/dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/.gitignore b/dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/.gitignore
new file mode 100644
index 00000000000..f940e0b554e
--- /dev/null
+++ b/dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/.gitignore
@@ -0,0 +1 @@
+kubeconfig
diff --git a/dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/kustomization.yaml b/dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/kustomization.yaml
new file mode 100644
index 00000000000..269acef9d28
--- /dev/null
+++ b/dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/kustomization.yaml
@@ -0,0 +1,22 @@
+apiVersion: kustomize.config.k8s.io/v1alpha1
+kind: Component
+
+resources:
+- secretbinding.yaml
+
+secretGenerator:
+# Instead of creating an empty "cloudprovider" secret, we create a secret containing the kubeconfig
+# for the local kind cluster. If the kubeconfig key in the cloudprovider key is present, provider-local
+# uses it to manage infrastructure resources instead of using its in-cluster ServiceAccount.
+# See docs/extensions/provider-local.md#credentials for details.
+# This is only needed for self-hosted shoots in the local setup because provider-local needs to manage
+# Kubernetes resources in a different cluster than the one it is running in.
+# Most notably, putting the initial kind cluster kubeconfig into the cloudprovider secret will effectively
+# prevent a control plane migration to another kind cluster in the local setup.
+# The kubeconfig file is copied to this directory by hack/kind-up.sh.
+- name: local
+ namespace: garden
+ options:
+ disableNameSuffixHash: true
+ files:
+ - kubeconfig
diff --git a/dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/secretbinding.yaml b/dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/secretbinding.yaml
new file mode 100644
index 00000000000..0c5e7325d06
--- /dev/null
+++ b/dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/secretbinding.yaml
@@ -0,0 +1,9 @@
+apiVersion: core.gardener.cloud/v1beta1
+kind: SecretBinding
+metadata:
+ name: local
+ namespace: garden
+provider:
+ type: local
+secretRef:
+ name: local
diff --git a/docs/extensions/provider-local.md b/docs/extensions/provider-local.md
index ea959155e1f..0b3db158d45 100644
--- a/docs/extensions/provider-local.md
+++ b/docs/extensions/provider-local.md
@@ -63,6 +63,15 @@ This CoreDNS instance is responsible for enabling the components running in the
It contains a static configuration to resolve the DNS names based on `local.gardener.cloud` to `istio-ingressgateway.istio-ingress.svc`.
+### Credentials
+
+By default, provider-local doesn't require any cloud provider credentials in the shoot's `{Secret,Credentials}Binding` as all infrastructure resources are deployed in the cluster where it runs.
+For this, provider-local uses its in-cluster config to connect to the Kubernetes API server of the seed/bootstrap cluster.
+However, provider-local also supports overwriting the credentials by specifying a `kubeconfig` in the shoot credentials secret.
+This is used in the local setup for [self-hosted shoots with managed infrastructure](../proposals/28-self-hosted-shoot-clusters.md#managed-infrastructure).
+Here, provider-local initially creates the infrastructure resources (e.g., Service, NetworkPolicies, machine Pods, etc.) in the kind cluster (during `gardenadm bootstrap`).
+Later on, `gardenadm init` restores the extension resources within the self-hosted shoot cluster itself, and provider-local – running in the shoot cluster now – needs credentials to access the kind cluster API server to keep managing those resources.
+
### Controllers
There are controllers for all resources in the `extensions.gardener.cloud/v1alpha1` API group except for `BackupBucket` and `BackupEntry`s.
diff --git a/hack/kind-up.sh b/hack/kind-up.sh
index 9e229967ca3..2d8b9875c1c 100755
--- a/hack/kind-up.sh
+++ b/hack/kind-up.sh
@@ -327,6 +327,13 @@ if [[ "$KUBECONFIG" != "$PATH_KUBECONFIG" ]]; then
fi
fi
+# Prepare a kubeconfig that can be used by provider-local as the provider credentials to talk to the kind cluster
+# from within the kind cluster and also from within a self-hosted shoot.
+# See docs/extensions/provider-local.md#credentials.
+if [[ "$CLUSTER_NAME" == "gardener-operator-local" ]] ; then
+ sed "s/127\.0\.0\.1:[0-9]\+/$CLUSTER_NAME-control-plane:6443/g" "$PATH_KUBECONFIG" > "$(dirname "$0")/../dev-setup/gardenconfig/components/credentials/secret-project-garden-with-kind-kubeconfig/kubeconfig"
+fi
+
# Prepare garden.local.gardener.cloud hostname that can be used everywhere to talk to the garden cluster.
# Historically, we used the docker container name for this, but this differs between clusters with different names
# and doesn't work in IPv6 kind clusters: https://github.com/kubernetes-sigs/kind/issues/3114
diff --git a/pkg/gardenadm/cmd/init/init.go b/pkg/gardenadm/cmd/init/init.go
index fb5950fb03f..f429d8df853 100644
--- a/pkg/gardenadm/cmd/init/init.go
+++ b/pkg/gardenadm/cmd/init/init.go
@@ -84,7 +84,7 @@ func run(ctx context.Context, opts *Options) error {
Name: "Deploying control plane namespace",
Fn: b.DeployControlPlaneNamespace,
})
- _ = g.Add(flow.Task{
+ deployCloudProviderSecret = g.Add(flow.Task{
Name: "Deploying cloud provider account secret",
Fn: b.DeployCloudProviderSecret,
SkipIf: b.Shoot.Credentials == nil,
@@ -163,6 +163,18 @@ func run(ctx context.Context, opts *Options) error {
Fn: b.ApplyNetworkPolicies,
Dependencies: flow.NewTaskIDs(waitUntilGardenerResourceManagerReady, deployExtensionControllers),
})
+ deployInfrastructure = g.Add(flow.Task{
+ Name: "Deploying Shoot infrastructure",
+ Fn: b.DeployInfrastructure,
+ SkipIf: !b.Shoot.HasManagedInfrastructure(),
+ Dependencies: flow.NewTaskIDs(initializeSecretsManagement, deployCloudProviderSecret, waitUntilExtensionControllersReady),
+ })
+ waitUntilInfrastructureReady = g.Add(flow.Task{
+ Name: "Waiting until Shoot infrastructure has been reconciled",
+ Fn: b.WaitForInfrastructure,
+ SkipIf: !b.Shoot.HasManagedInfrastructure(),
+ Dependencies: flow.NewTaskIDs(deployInfrastructure),
+ })
deployShootNamespaces = g.Add(flow.Task{
Name: "Deploying shoot namespaces system component",
Fn: b.Shoot.Components.SystemComponents.Namespaces.Deploy,
@@ -177,12 +189,12 @@ func run(ctx context.Context, opts *Options) error {
Name: "Deploying kube-proxy system component",
Fn: b.DeployKubeProxy,
SkipIf: !kubeProxyEnabled,
- Dependencies: flow.NewTaskIDs(waitUntilShootNamespacesReady, waitUntilExtensionControllersReady),
+ Dependencies: flow.NewTaskIDs(waitUntilShootNamespacesReady, waitUntilInfrastructureReady),
})
deployNetwork = g.Add(flow.Task{
Name: "Deploying shoot network plugin",
Fn: b.DeployNetwork,
- Dependencies: flow.NewTaskIDs(waitUntilShootNamespacesReady, waitUntilExtensionControllersReady),
+ Dependencies: flow.NewTaskIDs(waitUntilShootNamespacesReady, waitUntilInfrastructureReady),
})
waitUntilNetworkReady = g.Add(flow.Task{
Name: "Waiting until shoot network plugin has been reconciled",
diff --git a/pkg/provider-local/controller/infrastructure/actuator.go b/pkg/provider-local/controller/infrastructure/actuator.go
index dadcc1808af..3538422b760 100644
--- a/pkg/provider-local/controller/infrastructure/actuator.go
+++ b/pkg/provider-local/controller/infrastructure/actuator.go
@@ -27,17 +27,25 @@ import (
)
type actuator struct {
- client client.Client
+ // runtimeClient uses provider-local's in-cluster config, e.g., for the seed/bootstrap cluster it runs in.
+ // It's used to interact with extension objects. By default, it's also used as the provider client to interact with
+ // infrastructure resources, unless a kubeconfig is specified in the cloudprovider secret.
+ runtimeClient client.Client
}
// NewActuator creates a new Actuator that updates the status of the handled Infrastructure resources.
func NewActuator(mgr manager.Manager) infrastructure.Actuator {
return &actuator{
- client: mgr.GetClient(),
+ runtimeClient: mgr.GetClient(),
}
}
-func (a *actuator) Reconcile(ctx context.Context, _ logr.Logger, infrastructure *extensionsv1alpha1.Infrastructure, cluster *extensionscontroller.Cluster) error {
+func (a *actuator) Reconcile(ctx context.Context, log logr.Logger, infrastructure *extensionsv1alpha1.Infrastructure, cluster *extensionscontroller.Cluster) error {
+ providerClient, err := local.GetProviderClient(ctx, log, a.runtimeClient, infrastructure.Spec.SecretRef)
+ if err != nil {
+ return fmt.Errorf("could not create client for infrastructure resources: %w", err)
+ }
+
networkPolicyAllowMachinePods := emptyNetworkPolicy("allow-machine-pods", infrastructure.Namespace)
networkPolicyAllowMachinePods.Spec = networkingv1.NetworkPolicySpec{
Ingress: []networkingv1.NetworkPolicyIngressRule{{
@@ -101,7 +109,7 @@ func (a *actuator) Reconcile(ctx context.Context, _ logr.Logger, infrastructure
}
for _, obj := range objects {
- if err := a.client.Patch(ctx, obj, client.Apply, local.FieldOwner, client.ForceOwnership); err != nil {
+ if err := providerClient.Patch(ctx, obj, client.Apply, local.FieldOwner, client.ForceOwnership); err != nil {
return err
}
}
@@ -122,14 +130,18 @@ func (a *actuator) Reconcile(ctx context.Context, _ logr.Logger, infrastructure
if services := cluster.Shoot.Spec.Networking.Services; services != nil {
infrastructure.Status.Networking.Services = []string{*services}
}
- return a.client.Status().Patch(ctx, infrastructure, patch)
+
+ return a.runtimeClient.Status().Patch(ctx, infrastructure, patch)
}
-func (a *actuator) Delete(ctx context.Context, _ logr.Logger, infrastructure *extensionsv1alpha1.Infrastructure, _ *extensionscontroller.Cluster) error {
- return kubernetesutils.DeleteObjects(ctx, a.client,
+func (a *actuator) Delete(ctx context.Context, log logr.Logger, infrastructure *extensionsv1alpha1.Infrastructure, _ *extensionscontroller.Cluster) error {
+ providerClient, err := local.GetProviderClient(ctx, log, a.runtimeClient, infrastructure.Spec.SecretRef)
+ if err != nil {
+ return fmt.Errorf("could not create client for infrastructure resources: %w", err)
+ }
+
+ return kubernetesutils.DeleteObjects(ctx, providerClient,
emptyNetworkPolicy("allow-machine-pods", infrastructure.Namespace),
- emptyNetworkPolicy("allow-to-istio-ingress-gateway", infrastructure.Namespace),
- emptyNetworkPolicy("allow-to-provider-local-coredns", infrastructure.Namespace),
emptyService(infrastructure.Namespace),
&metav1.PartialObjectMetadata{TypeMeta: metav1.TypeMeta{APIVersion: "crd.projectcalico.org/v1", Kind: "IPPool"}, ObjectMeta: metav1.ObjectMeta{Name: IPPoolName(infrastructure.Namespace, string(gardencorev1beta1.IPFamilyIPv4))}},
&metav1.PartialObjectMetadata{TypeMeta: metav1.TypeMeta{APIVersion: "crd.projectcalico.org/v1", Kind: "IPPool"}, ObjectMeta: metav1.ObjectMeta{Name: IPPoolName(infrastructure.Namespace, string(gardencorev1beta1.IPFamilyIPv6))}},
diff --git a/pkg/provider-local/local/client.go b/pkg/provider-local/local/client.go
new file mode 100644
index 00000000000..b782254fe84
--- /dev/null
+++ b/pkg/provider-local/local/client.go
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package local
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/go-logr/logr"
+ corev1 "k8s.io/api/core/v1"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+
+ "github.com/gardener/gardener/pkg/client/kubernetes"
+ kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
+)
+
+// GetProviderClient returns a Kubernetes client for the cluster in which provider-local should manage infrastructure
+// resources, e.g., Services, NetworkPolicies, machine Pods, etc. If the cloudprovider secret contains a kubeconfig,
+// a client for that kubeconfig is created. Otherwise, the given client for the runtime cluster is returned.
+// See https://github.com/gardener/gardener/blob/master/docs/extensions/provider-local.md#credentials.
+func GetProviderClient(ctx context.Context, log logr.Logger, runtimeClient client.Client, secretRef corev1.SecretReference) (client.Client, error) {
+ cloudProviderSecret, err := kubernetesutils.GetSecretByReference(ctx, runtimeClient, &secretRef)
+ if err != nil {
+ return nil, fmt.Errorf("could not retrieve cloudprovider secret: %w", err)
+ }
+
+ if len(cloudProviderSecret.Data[kubernetes.KubeConfig]) == 0 {
+ log.Info("Using in-cluster config for provider client as no kubeconfig is specified in the cloudprovider secret")
+ return runtimeClient, nil
+ }
+
+ clientSet, err := kubernetes.NewClientFromBytes(cloudProviderSecret.Data[kubernetes.KubeConfig],
+ kubernetes.WithClientOptions(client.Options{Scheme: kubernetes.SeedScheme}),
+ kubernetes.WithDisabledCachedClient(),
+ )
+ if err != nil {
+ return nil, fmt.Errorf("could not create client from cloudprovider secret: %w", err)
+ }
+
+ log.Info("Using kubeconfig from cloudprovider secret for provider client")
+ return clientSet.Client(), nil
+}
diff --git a/test/e2e/gardenadm/managedinfra/gardenadm.go b/test/e2e/gardenadm/managedinfra/gardenadm.go
index bc216288ec4..b7670dcd22e 100644
--- a/test/e2e/gardenadm/managedinfra/gardenadm.go
+++ b/test/e2e/gardenadm/managedinfra/gardenadm.go
@@ -200,7 +200,11 @@ var _ = Describe("gardenadm managed infrastructure scenario tests", Label("garde
kubeconfig = strings.ReplaceAll(string(kubeconfigSecret.Data["kubeconfig"]), "api.root.garden.local.gardener.cloud", fmt.Sprintf("localhost:%d", localPort))
}, SpecTimeout(time.Minute))
- var shootClientSet kubernetes.Interface
+ var (
+ shootClientSet kubernetes.Interface
+ shootKomega Komega
+ )
+
It("should connect to the shoot", func(ctx SpecContext) {
By("Forward port to control plane machine pod")
fw, err := kubernetes.SetupPortForwarder(portForwardCtx, RuntimeClient.RESTConfig(), technicalID, machinePodName(ctx, technicalID, 0), localPort, 443)
@@ -222,6 +226,8 @@ var _ = Describe("gardenadm managed infrastructure scenario tests", Label("garde
)
return err
}).Should(Succeed())
+
+ shootKomega = New(shootClientSet.Client())
}, SpecTimeout(time.Minute))
It("should restore all persisted secrets in the shoot", func(ctx SpecContext) {
@@ -244,6 +250,21 @@ var _ = Describe("gardenadm managed infrastructure scenario tests", Label("garde
Expect(shootmigration.ComparePersistedSecrets(persistedSecrets, shootSecrets)).To(Succeed())
}, SpecTimeout(time.Minute))
+ It("should deploy/restore the infrastructure in the shoot", func(ctx SpecContext) {
+ infra := &extensionsv1alpha1.Infrastructure{ObjectMeta: metav1.ObjectMeta{Name: shootName, Namespace: "kube-system"}}
+ Eventually(ctx, shootKomega.Object(infra)).Should(BeHealthy(health.CheckExtensionObject))
+ }, SpecTimeout(time.Minute))
+
+ It("should create infrastructure resources in the bootstrap cluster", func(ctx SpecContext) {
+ // Verify that the infrastructure created in the shoot has corresponding resources in the bootstrap cluster, but
+ // not in the shoot itself. This is specific to provider-local as the infrastructure resources are managed in the
+ // bootstrap cluster. This check is unrelated to gardenadm functionality, but serves as an additional verification
+ // that the functionality of using a non-default provider client in provider-local works as expected.
+ service := &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "machines", Namespace: technicalID}}
+ Consistently(ctx, shootKomega.Get(service)).Should(BeNotFoundError())
+ Eventually(ctx, Get(service)).Should(Succeed())
+ }, SpecTimeout(time.Minute))
+
It("should finish successfully", func(ctx SpecContext) {
Wait(ctx, session)
Eventually(ctx, session.Out).Should(gbytes.Say("work in progress"))
From 3918a061e47c841da5f9799a8ec114311a1bfe6c Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Mon, 10 Nov 2025 10:57:42 +0100
Subject: [PATCH 061/176] Update module github.com/fluent/fluent-operator/v3 to
v3.5.0 (#13306)
* Update module github.com/fluent/fluent-operator/v3 to v3.5.0
* chore: Run `make generate`
* chore: Remove toolchain from go.mod and keep bump to `go 1.24.5`
---------
Co-authored-by: Marc Vornetran
---
...rd-fluentbit.fluent.io_clusterfilters.yaml | 35 +++++---
...bit.fluent.io_clusterfluentbitconfigs.yaml | 6 +-
...crd-fluentbit.fluent.io_clusterinputs.yaml | 84 +++++++++++++++++--
...rd-fluentbit.fluent.io_clusteroutputs.yaml | 63 ++++++++++++--
...rd-fluentbit.fluent.io_clusterparsers.yaml | 13 +++
...10-crd-fluentbit.fluent.io_collectors.yaml | 4 +
.../10-crd-fluentbit.fluent.io_filters.yaml | 35 +++++---
...-fluentbit.fluent.io_fluentbitconfigs.yaml | 6 +-
.../10-crd-fluentbit.fluent.io_outputs.yaml | 63 ++++++++++++--
.../10-crd-fluentbit.fluent.io_parsers.yaml | 13 +++
go.mod | 4 +-
go.sum | 4 +-
...rd-fluentbit.fluent.io_clusterfilters.yaml | 35 +++++---
...bit.fluent.io_clusterfluentbitconfigs.yaml | 6 +-
...crd-fluentbit.fluent.io_clusterinputs.yaml | 84 +++++++++++++++++--
...rd-fluentbit.fluent.io_clusteroutputs.yaml | 63 ++++++++++++--
...rd-fluentbit.fluent.io_clusterparsers.yaml | 13 +++
.../crd-fluentbit.fluent.io_collectors.yaml | 4 +
.../crd-fluentbit.fluent.io_filters.yaml | 35 +++++---
...-fluentbit.fluent.io_fluentbitconfigs.yaml | 6 +-
.../crd-fluentbit.fluent.io_outputs.yaml | 63 ++++++++++++--
.../crd-fluentbit.fluent.io_parsers.yaml | 13 +++
22 files changed, 552 insertions(+), 100 deletions(-)
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfilters.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfilters.yaml
index 624039566a0..4a6e32eb438 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfilters.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfilters.yaml
@@ -85,7 +85,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -131,7 +131,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -279,6 +279,10 @@ spec:
Include Kubernetes namespace metadata only and no pod metadata.
If this is set, the values of Labels and Annotations are ignored.
type: boolean
+ ownerReferences:
+ description: Include Kubernetes owner references in the
+ extra metadata.
+ type: boolean
regexParser:
description: |-
Set an alternative Parser to process record Tag and extract pod_name, namespace_name, container_name and docker_id.
@@ -287,7 +291,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -313,6 +317,11 @@ spec:
instead of calling Kube Server API to enhance the log.
This could mitigate the Kube API heavy traffic issue for large cluster.
type: boolean
+ useTagForMeta:
+ description: If true, Kubernetes metadata (e.g., pod_name,
+ container_name, namespace_name etc) will be extracted
+ from the tag itself.
+ type: boolean
type: object
logToMetrics:
description: LogToMetrics defines a Log to Metrics Filter configuration.
@@ -387,7 +396,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -425,7 +434,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -548,7 +557,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -671,7 +680,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -711,7 +720,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -751,7 +760,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -788,7 +797,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -826,7 +835,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -864,7 +873,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -901,7 +910,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
index 2aaeb309652..665720d7141 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
@@ -299,6 +299,10 @@ spec:
type: string
emitterStorageType:
type: string
+ enableChunkTrace:
+ description: Enable input/output tracing on debug images, controlled
+ more granualry via the http API
+ type: boolean
flushSeconds:
description: Interval to flush output
type: number
@@ -341,7 +345,7 @@ spec:
type: boolean
httpListen:
description: Address to listen
- pattern: ^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$
+ pattern: ^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(([A-Fa-f0-9:]+:+)+[A-Fa-f0-9]*)$
type: string
httpPort:
description: Port to listen
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterinputs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterinputs.yaml
index f3813ba4343..d809f0dea06 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterinputs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterinputs.yaml
@@ -91,7 +91,7 @@ spec:
format: int32
type: integer
tag:
- description: Tag name associated to all records comming from this
+ description: Tag name associated to all records coming from this
plugin.
type: string
type: object
@@ -156,7 +156,7 @@ spec:
properties:
bufferMaxSize:
description: |-
- Specify maximum buffer memory size used to recieve a forward message.
+ Specify maximum buffer memory size used to receive a forward message.
The value must be according to the Unit Size specification.
pattern: ^\d+(k|K|KB|kb|m|M|MB|mb|g|G|GB|gb)?$
type: string
@@ -188,7 +188,7 @@ spec:
a separate thread which helps to desaturate the main pipeline.
type: string
unixPath:
- description: Specify the path to unix socket to recieve a forward
+ description: Specify the path to unix socket to receive a forward
message. If set, Listen and port are ignnored.
type: string
unixPerm:
@@ -353,7 +353,7 @@ spec:
description: API Server end-point
type: string
tag:
- description: Tag name associated to all records comming from this
+ description: Tag name associated to all records coming from this
plugin.
type: string
tlsDebug:
@@ -432,7 +432,7 @@ spec:
host operating system, default is 5 seconds.
type: string
tag:
- description: Tag name associated to all records comming from this
+ description: Tag name associated to all records coming from this
plugin.
type: string
type: object
@@ -507,7 +507,7 @@ spec:
description: 'The interval to scrape metrics, default: 10s'
type: string
tag:
- description: Tag name associated to all records comming from this
+ description: Tag name associated to all records coming from this
plugin
type: string
type: object
@@ -578,6 +578,74 @@ spec:
description: Specify the key where the source address will be
injected.
type: string
+ tls:
+ description: Specify TLS connector options.
+ properties:
+ caFile:
+ description: Absolute path to CA certificate file
+ type: string
+ caPath:
+ description: Absolute path to scan for certificate files
+ type: string
+ crtFile:
+ description: Absolute path to Certificate file
+ type: string
+ debug:
+ description: |-
+ Set TLS debug verbosity level.
+ It accept the following values: 0 (No debug), 1 (Error), 2 (State change), 3 (Informational) and 4 Verbose
+ enum:
+ - 0
+ - 1
+ - 2
+ - 3
+ - 4
+ format: int32
+ type: integer
+ keyFile:
+ description: Absolute path to private Key file
+ type: string
+ keyPassword:
+ description: Optional password for tls.key_file file
+ properties:
+ valueFrom:
+ description: ValueSource defines how to find a value's
+ key.
+ properties:
+ secretKeyRef:
+ description: Selects a key of a secret in the pod's
+ namespace
+ properties:
+ key:
+ description: The key of the secret to select from. Must
+ be a valid secret key.
+ type: string
+ name:
+ default: ""
+ description: |-
+ Name of the referent.
+ This field is effectively required, but due to backwards compatibility is
+ allowed to be empty. Instances of this type with an empty value here are
+ almost certainly wrong.
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+ type: string
+ optional:
+ description: Specify whether the Secret or its
+ key must be defined
+ type: boolean
+ required:
+ - key
+ type: object
+ x-kubernetes-map-type: atomic
+ type: object
+ type: object
+ verify:
+ description: Force certificate validation
+ type: boolean
+ vhost:
+ description: Hostname to be used for TLS SNI extension
+ type: string
+ type: object
unixPerm:
description: 'If Mode is set to unix_tcp or unix_udp, set the
permission of the Unix socket file, default: 0644'
@@ -692,6 +760,10 @@ spec:
description: Specify the database file to keep track of monitored
files and offsets.
type: string
+ dbLocking:
+ description: Specify that the database will be accessed only by
+ Fluent Bit.
+ type: boolean
dbSync:
description: 'Set a default synchronization (I/O) method. Values:
Extra, Full, Normal, Off.'
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusteroutputs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusteroutputs.yaml
index f53fd251fb4..051a0b7eac0 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusteroutputs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusteroutputs.yaml
@@ -65,6 +65,18 @@ spec:
- appendblob
- blockblob
type: string
+ bufferingEnabled:
+ description: Enable buffering into disk before ingesting into
+ Azure Blob.
+ type: boolean
+ compressBlob:
+ description: 'Optional: Enables GZIP compression in the final
+ blockblob file. This option isn''t compatible when blob_type
+ = appendblob.'
+ enum:
+ - "on"
+ - "off"
+ type: string
containerName:
description: Name of the container that will contain the blobs
type: string
@@ -240,6 +252,18 @@ spec:
description: Hostname to be used for TLS SNI extension
type: string
type: object
+ uploadFileSize:
+ default: 200M
+ description: Specifies the size of files to be uploaded in MB.
+ Defaults to 200M.
+ type: string
+ uploadTimeout:
+ default: 30m
+ description: Optional. Specify a timeout for uploads. Fluent Bit
+ will start ingesting buffer files which have been created more
+ than x minutes ago and haven't reached upload_file_size limit
+ yet. Defaults to 30m.
+ type: string
required:
- accountName
- containerName
@@ -1981,7 +2005,7 @@ spec:
192.168.1.4:9092.'
type: string
dynamicTopic:
- description: adds unknown topics (found in Topic_Key) to Topics.
+ description: Adds unknown topics (found in Topic_Key) to Topics.
So in Topics only a default topic needs to be configured
type: boolean
format:
@@ -2067,6 +2091,7 @@ spec:
type: string
region:
description: The AWS region.
+ minLength: 1
type: string
roleARN:
description: ARN of an IAM role to assume (for cross account access).
@@ -2323,6 +2348,21 @@ spec:
items:
type: string
type: array
+ structuredMetadata:
+ additionalProperties:
+ type: string
+ description: |-
+ Stream structured metadata for API request. It can be multiple comma separated key=value pairs.
+ This is used for high cardinality data that isn't suited for using labels.
+ Only supported in Loki 3.0+ with schema v13 and TSDB storage.
+ type: object
+ structuredMetadataKeys:
+ description: |-
+ Optional list of record keys that will be placed as structured metadata.
+ This allows using record accessor patterns (e.g. $kubernetes['pod_name']) to reference record keys.
+ items:
+ type: string
+ type: array
tenantID:
description: |-
Tenant ID used by default to push logs to Loki.
@@ -2682,7 +2722,7 @@ spec:
type: integer
replaceDots:
description: When enabled, replace field name dots with underscore,
- required by Elasticsearch 2.0-2.3.
+ required by Opensearch 2.0-2.3.
type: boolean
suppressTypeName:
description: When enabled, mapping types is removed and Type option
@@ -2781,12 +2821,12 @@ spec:
for the current output logical destination.
type: string
traceError:
- description: When enabled print the elasticsearch API calls to
- stdout when elasticsearch returns an error
+ description: When enabled print the Opensearch API calls to stdout
+ when Opensearch returns an error
type: boolean
traceOutput:
- description: When enabled print the elasticsearch API calls to
- stdout (for diag only)
+ description: When enabled print the Opensearch API calls to stdout
+ (for diag only)
type: boolean
type:
description: Type name
@@ -3437,6 +3477,11 @@ spec:
description: Use the S3 PutObject API, instead of the multipart
upload API.
type: boolean
+ Workers:
+ description: Specify number of worker threads to use to output
+ to S3
+ format: int32
+ type: integer
tls:
description: Fluent Bit provides integrated support for Transport
Layer Security (TLS) and it predecessor Secure Sockets Layer
@@ -3876,7 +3921,7 @@ spec:
description: Set resource types of data
type: string
resourceLabels:
- description: Optional list of comma seperated strings. Setting
+ description: Optional list of comma separated strings. Setting
these fields overrides the Stackdriver monitored resource API
values
items:
@@ -3958,6 +4003,10 @@ spec:
description: Identifier for a task within a namespace. Required
if Resource is generic_task
type: string
+ textPayloadKey:
+ description: The key used to select the text payload from the
+ record
+ type: string
workers:
description: Number of dedicated threads for the Stackdriver Output
Plugin
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterparsers.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterparsers.yaml
index 0e2983036e5..55f4e0d914a 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_clusterparsers.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_clusterparsers.yaml
@@ -74,7 +74,20 @@ spec:
type: object
logfmt:
description: Logfmt defines logfmt parser configuration.
+ properties:
+ timeFormat:
+ description: Time_Format, eg. %Y-%m-%dT%H:%M:%S %z
+ type: string
+ timeKeep:
+ description: Time_Keep
+ type: boolean
+ timeKey:
+ description: Time_Key
+ type: string
type: object
+ x-kubernetes-validations:
+ - message: logfmt must not be null
+ rule: self != null
ltsv:
description: LTSV defines ltsv parser configuration.
properties:
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_collectors.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_collectors.yaml
index c99f8c00ad4..704bde01752 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_collectors.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_collectors.yaml
@@ -1502,6 +1502,10 @@ spec:
- verbs
type: object
type: array
+ replicas:
+ description: Replicas is the number of collector replicas to deploy
+ format: int32
+ type: integer
resources:
description: Compute Resources required by container.
properties:
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_filters.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_filters.yaml
index 55135835718..f21ee911c8e 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_filters.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_filters.yaml
@@ -85,7 +85,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -131,7 +131,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -279,6 +279,10 @@ spec:
Include Kubernetes namespace metadata only and no pod metadata.
If this is set, the values of Labels and Annotations are ignored.
type: boolean
+ ownerReferences:
+ description: Include Kubernetes owner references in the
+ extra metadata.
+ type: boolean
regexParser:
description: |-
Set an alternative Parser to process record Tag and extract pod_name, namespace_name, container_name and docker_id.
@@ -287,7 +291,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -313,6 +317,11 @@ spec:
instead of calling Kube Server API to enhance the log.
This could mitigate the Kube API heavy traffic issue for large cluster.
type: boolean
+ useTagForMeta:
+ description: If true, Kubernetes metadata (e.g., pod_name,
+ container_name, namespace_name etc) will be extracted
+ from the tag itself.
+ type: boolean
type: object
logToMetrics:
description: LogToMetrics defines a Log to Metrics Filter configuration.
@@ -387,7 +396,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -425,7 +434,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -548,7 +557,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -671,7 +680,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -711,7 +720,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -751,7 +760,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -788,7 +797,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -826,7 +835,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -864,7 +873,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -901,7 +910,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbitconfigs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbitconfigs.yaml
index aafe67c640f..9a5ef6585db 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbitconfigs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_fluentbitconfigs.yaml
@@ -331,6 +331,10 @@ spec:
type: string
emitterStorageType:
type: string
+ enableChunkTrace:
+ description: Enable input/output tracing on debug images, controlled
+ more granualry via the http API
+ type: boolean
flushSeconds:
description: Interval to flush output
type: number
@@ -373,7 +377,7 @@ spec:
type: boolean
httpListen:
description: Address to listen
- pattern: ^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$
+ pattern: ^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(([A-Fa-f0-9:]+:+)+[A-Fa-f0-9]*)$
type: string
httpPort:
description: Port to listen
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_outputs.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_outputs.yaml
index 7da1e0b4203..97a511871ba 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_outputs.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_outputs.yaml
@@ -65,6 +65,18 @@ spec:
- appendblob
- blockblob
type: string
+ bufferingEnabled:
+ description: Enable buffering into disk before ingesting into
+ Azure Blob.
+ type: boolean
+ compressBlob:
+ description: 'Optional: Enables GZIP compression in the final
+ blockblob file. This option isn''t compatible when blob_type
+ = appendblob.'
+ enum:
+ - "on"
+ - "off"
+ type: string
containerName:
description: Name of the container that will contain the blobs
type: string
@@ -240,6 +252,18 @@ spec:
description: Hostname to be used for TLS SNI extension
type: string
type: object
+ uploadFileSize:
+ default: 200M
+ description: Specifies the size of files to be uploaded in MB.
+ Defaults to 200M.
+ type: string
+ uploadTimeout:
+ default: 30m
+ description: Optional. Specify a timeout for uploads. Fluent Bit
+ will start ingesting buffer files which have been created more
+ than x minutes ago and haven't reached upload_file_size limit
+ yet. Defaults to 30m.
+ type: string
required:
- accountName
- containerName
@@ -1981,7 +2005,7 @@ spec:
192.168.1.4:9092.'
type: string
dynamicTopic:
- description: adds unknown topics (found in Topic_Key) to Topics.
+ description: Adds unknown topics (found in Topic_Key) to Topics.
So in Topics only a default topic needs to be configured
type: boolean
format:
@@ -2067,6 +2091,7 @@ spec:
type: string
region:
description: The AWS region.
+ minLength: 1
type: string
roleARN:
description: ARN of an IAM role to assume (for cross account access).
@@ -2323,6 +2348,21 @@ spec:
items:
type: string
type: array
+ structuredMetadata:
+ additionalProperties:
+ type: string
+ description: |-
+ Stream structured metadata for API request. It can be multiple comma separated key=value pairs.
+ This is used for high cardinality data that isn't suited for using labels.
+ Only supported in Loki 3.0+ with schema v13 and TSDB storage.
+ type: object
+ structuredMetadataKeys:
+ description: |-
+ Optional list of record keys that will be placed as structured metadata.
+ This allows using record accessor patterns (e.g. $kubernetes['pod_name']) to reference record keys.
+ items:
+ type: string
+ type: array
tenantID:
description: |-
Tenant ID used by default to push logs to Loki.
@@ -2682,7 +2722,7 @@ spec:
type: integer
replaceDots:
description: When enabled, replace field name dots with underscore,
- required by Elasticsearch 2.0-2.3.
+ required by Opensearch 2.0-2.3.
type: boolean
suppressTypeName:
description: When enabled, mapping types is removed and Type option
@@ -2781,12 +2821,12 @@ spec:
for the current output logical destination.
type: string
traceError:
- description: When enabled print the elasticsearch API calls to
- stdout when elasticsearch returns an error
+ description: When enabled print the Opensearch API calls to stdout
+ when Opensearch returns an error
type: boolean
traceOutput:
- description: When enabled print the elasticsearch API calls to
- stdout (for diag only)
+ description: When enabled print the Opensearch API calls to stdout
+ (for diag only)
type: boolean
type:
description: Type name
@@ -3437,6 +3477,11 @@ spec:
description: Use the S3 PutObject API, instead of the multipart
upload API.
type: boolean
+ Workers:
+ description: Specify number of worker threads to use to output
+ to S3
+ format: int32
+ type: integer
tls:
description: Fluent Bit provides integrated support for Transport
Layer Security (TLS) and it predecessor Secure Sockets Layer
@@ -3876,7 +3921,7 @@ spec:
description: Set resource types of data
type: string
resourceLabels:
- description: Optional list of comma seperated strings. Setting
+ description: Optional list of comma separated strings. Setting
these fields overrides the Stackdriver monitored resource API
values
items:
@@ -3958,6 +4003,10 @@ spec:
description: Identifier for a task within a namespace. Required
if Resource is generic_task
type: string
+ textPayloadKey:
+ description: The key used to select the text payload from the
+ record
+ type: string
workers:
description: Number of dedicated threads for the Stackdriver Output
Plugin
diff --git a/example/seed-crds/10-crd-fluentbit.fluent.io_parsers.yaml b/example/seed-crds/10-crd-fluentbit.fluent.io_parsers.yaml
index 6bfe5e95284..1c117577242 100644
--- a/example/seed-crds/10-crd-fluentbit.fluent.io_parsers.yaml
+++ b/example/seed-crds/10-crd-fluentbit.fluent.io_parsers.yaml
@@ -74,7 +74,20 @@ spec:
type: object
logfmt:
description: Logfmt defines logfmt parser configuration.
+ properties:
+ timeFormat:
+ description: Time_Format, eg. %Y-%m-%dT%H:%M:%S %z
+ type: string
+ timeKeep:
+ description: Time_Keep
+ type: boolean
+ timeKey:
+ description: Time_Key
+ type: string
type: object
+ x-kubernetes-validations:
+ - message: logfmt must not be null
+ rule: self != null
ltsv:
description: LTSV defines ltsv parser configuration.
properties:
diff --git a/go.mod b/go.mod
index 77e2501e53a..73870b6409e 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module github.com/gardener/gardener
-go 1.24.0
+go 1.24.5
require (
github.com/Masterminds/semver/v3 v3.4.0
@@ -12,7 +12,7 @@ require (
github.com/coreos/go-systemd/v22 v22.6.0
github.com/distribution/distribution/v3 v3.0.0
github.com/docker/cli v28.5.2+incompatible
- github.com/fluent/fluent-operator/v3 v3.3.0
+ github.com/fluent/fluent-operator/v3 v3.5.0
github.com/gardener/cert-management v0.19.0
github.com/gardener/dependency-watchdog v1.6.0
github.com/gardener/etcd-druid/api v0.33.0
diff --git a/go.sum b/go.sum
index 10ee032a51a..3fcce88f487 100644
--- a/go.sum
+++ b/go.sum
@@ -224,8 +224,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
-github.com/fluent/fluent-operator/v3 v3.3.0 h1:zBtt8IOVSyTiywnmom3V2byqIi2ZXMCCKBUx/4bnFBk=
-github.com/fluent/fluent-operator/v3 v3.3.0/go.mod h1:x54zzJ60QYJ6jnN7n9/Mseyaz9oWjSO99hbhVXJaar0=
+github.com/fluent/fluent-operator/v3 v3.5.0 h1:soNOaXLmN7VQg1mlHDDKGQ9itYpvgycWstMqXvOD66g=
+github.com/fluent/fluent-operator/v3 v3.5.0/go.mod h1:6phBFSu5/+81dbwfizIprNirr7VlbnkhcawbSe7r7NM=
github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=
github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfilters.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfilters.yaml
index 624039566a0..4a6e32eb438 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfilters.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfilters.yaml
@@ -85,7 +85,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -131,7 +131,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -279,6 +279,10 @@ spec:
Include Kubernetes namespace metadata only and no pod metadata.
If this is set, the values of Labels and Annotations are ignored.
type: boolean
+ ownerReferences:
+ description: Include Kubernetes owner references in the
+ extra metadata.
+ type: boolean
regexParser:
description: |-
Set an alternative Parser to process record Tag and extract pod_name, namespace_name, container_name and docker_id.
@@ -287,7 +291,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -313,6 +317,11 @@ spec:
instead of calling Kube Server API to enhance the log.
This could mitigate the Kube API heavy traffic issue for large cluster.
type: boolean
+ useTagForMeta:
+ description: If true, Kubernetes metadata (e.g., pod_name,
+ container_name, namespace_name etc) will be extracted
+ from the tag itself.
+ type: boolean
type: object
logToMetrics:
description: LogToMetrics defines a Log to Metrics Filter configuration.
@@ -387,7 +396,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -425,7 +434,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -548,7 +557,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -671,7 +680,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -711,7 +720,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -751,7 +760,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -788,7 +797,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -826,7 +835,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -864,7 +873,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -901,7 +910,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
index 2aaeb309652..665720d7141 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterfluentbitconfigs.yaml
@@ -299,6 +299,10 @@ spec:
type: string
emitterStorageType:
type: string
+ enableChunkTrace:
+ description: Enable input/output tracing on debug images, controlled
+ more granualry via the http API
+ type: boolean
flushSeconds:
description: Interval to flush output
type: number
@@ -341,7 +345,7 @@ spec:
type: boolean
httpListen:
description: Address to listen
- pattern: ^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$
+ pattern: ^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(([A-Fa-f0-9:]+:+)+[A-Fa-f0-9]*)$
type: string
httpPort:
description: Port to listen
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterinputs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterinputs.yaml
index f3813ba4343..d809f0dea06 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterinputs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterinputs.yaml
@@ -91,7 +91,7 @@ spec:
format: int32
type: integer
tag:
- description: Tag name associated to all records comming from this
+ description: Tag name associated to all records coming from this
plugin.
type: string
type: object
@@ -156,7 +156,7 @@ spec:
properties:
bufferMaxSize:
description: |-
- Specify maximum buffer memory size used to recieve a forward message.
+ Specify maximum buffer memory size used to receive a forward message.
The value must be according to the Unit Size specification.
pattern: ^\d+(k|K|KB|kb|m|M|MB|mb|g|G|GB|gb)?$
type: string
@@ -188,7 +188,7 @@ spec:
a separate thread which helps to desaturate the main pipeline.
type: string
unixPath:
- description: Specify the path to unix socket to recieve a forward
+ description: Specify the path to unix socket to receive a forward
message. If set, Listen and port are ignnored.
type: string
unixPerm:
@@ -353,7 +353,7 @@ spec:
description: API Server end-point
type: string
tag:
- description: Tag name associated to all records comming from this
+ description: Tag name associated to all records coming from this
plugin.
type: string
tlsDebug:
@@ -432,7 +432,7 @@ spec:
host operating system, default is 5 seconds.
type: string
tag:
- description: Tag name associated to all records comming from this
+ description: Tag name associated to all records coming from this
plugin.
type: string
type: object
@@ -507,7 +507,7 @@ spec:
description: 'The interval to scrape metrics, default: 10s'
type: string
tag:
- description: Tag name associated to all records comming from this
+ description: Tag name associated to all records coming from this
plugin
type: string
type: object
@@ -578,6 +578,74 @@ spec:
description: Specify the key where the source address will be
injected.
type: string
+ tls:
+ description: Specify TLS connector options.
+ properties:
+ caFile:
+ description: Absolute path to CA certificate file
+ type: string
+ caPath:
+ description: Absolute path to scan for certificate files
+ type: string
+ crtFile:
+ description: Absolute path to Certificate file
+ type: string
+ debug:
+ description: |-
+ Set TLS debug verbosity level.
+ It accept the following values: 0 (No debug), 1 (Error), 2 (State change), 3 (Informational) and 4 Verbose
+ enum:
+ - 0
+ - 1
+ - 2
+ - 3
+ - 4
+ format: int32
+ type: integer
+ keyFile:
+ description: Absolute path to private Key file
+ type: string
+ keyPassword:
+ description: Optional password for tls.key_file file
+ properties:
+ valueFrom:
+ description: ValueSource defines how to find a value's
+ key.
+ properties:
+ secretKeyRef:
+ description: Selects a key of a secret in the pod's
+ namespace
+ properties:
+ key:
+ description: The key of the secret to select from. Must
+ be a valid secret key.
+ type: string
+ name:
+ default: ""
+ description: |-
+ Name of the referent.
+ This field is effectively required, but due to backwards compatibility is
+ allowed to be empty. Instances of this type with an empty value here are
+ almost certainly wrong.
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+ type: string
+ optional:
+ description: Specify whether the Secret or its
+ key must be defined
+ type: boolean
+ required:
+ - key
+ type: object
+ x-kubernetes-map-type: atomic
+ type: object
+ type: object
+ verify:
+ description: Force certificate validation
+ type: boolean
+ vhost:
+ description: Hostname to be used for TLS SNI extension
+ type: string
+ type: object
unixPerm:
description: 'If Mode is set to unix_tcp or unix_udp, set the
permission of the Unix socket file, default: 0644'
@@ -692,6 +760,10 @@ spec:
description: Specify the database file to keep track of monitored
files and offsets.
type: string
+ dbLocking:
+ description: Specify that the database will be accessed only by
+ Fluent Bit.
+ type: boolean
dbSync:
description: 'Set a default synchronization (I/O) method. Values:
Extra, Full, Normal, Off.'
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusteroutputs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusteroutputs.yaml
index f53fd251fb4..051a0b7eac0 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusteroutputs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusteroutputs.yaml
@@ -65,6 +65,18 @@ spec:
- appendblob
- blockblob
type: string
+ bufferingEnabled:
+ description: Enable buffering into disk before ingesting into
+ Azure Blob.
+ type: boolean
+ compressBlob:
+ description: 'Optional: Enables GZIP compression in the final
+ blockblob file. This option isn''t compatible when blob_type
+ = appendblob.'
+ enum:
+ - "on"
+ - "off"
+ type: string
containerName:
description: Name of the container that will contain the blobs
type: string
@@ -240,6 +252,18 @@ spec:
description: Hostname to be used for TLS SNI extension
type: string
type: object
+ uploadFileSize:
+ default: 200M
+ description: Specifies the size of files to be uploaded in MB.
+ Defaults to 200M.
+ type: string
+ uploadTimeout:
+ default: 30m
+ description: Optional. Specify a timeout for uploads. Fluent Bit
+ will start ingesting buffer files which have been created more
+ than x minutes ago and haven't reached upload_file_size limit
+ yet. Defaults to 30m.
+ type: string
required:
- accountName
- containerName
@@ -1981,7 +2005,7 @@ spec:
192.168.1.4:9092.'
type: string
dynamicTopic:
- description: adds unknown topics (found in Topic_Key) to Topics.
+ description: Adds unknown topics (found in Topic_Key) to Topics.
So in Topics only a default topic needs to be configured
type: boolean
format:
@@ -2067,6 +2091,7 @@ spec:
type: string
region:
description: The AWS region.
+ minLength: 1
type: string
roleARN:
description: ARN of an IAM role to assume (for cross account access).
@@ -2323,6 +2348,21 @@ spec:
items:
type: string
type: array
+ structuredMetadata:
+ additionalProperties:
+ type: string
+ description: |-
+ Stream structured metadata for API request. It can be multiple comma separated key=value pairs.
+ This is used for high cardinality data that isn't suited for using labels.
+ Only supported in Loki 3.0+ with schema v13 and TSDB storage.
+ type: object
+ structuredMetadataKeys:
+ description: |-
+ Optional list of record keys that will be placed as structured metadata.
+ This allows using record accessor patterns (e.g. $kubernetes['pod_name']) to reference record keys.
+ items:
+ type: string
+ type: array
tenantID:
description: |-
Tenant ID used by default to push logs to Loki.
@@ -2682,7 +2722,7 @@ spec:
type: integer
replaceDots:
description: When enabled, replace field name dots with underscore,
- required by Elasticsearch 2.0-2.3.
+ required by Opensearch 2.0-2.3.
type: boolean
suppressTypeName:
description: When enabled, mapping types is removed and Type option
@@ -2781,12 +2821,12 @@ spec:
for the current output logical destination.
type: string
traceError:
- description: When enabled print the elasticsearch API calls to
- stdout when elasticsearch returns an error
+ description: When enabled print the Opensearch API calls to stdout
+ when Opensearch returns an error
type: boolean
traceOutput:
- description: When enabled print the elasticsearch API calls to
- stdout (for diag only)
+ description: When enabled print the Opensearch API calls to stdout
+ (for diag only)
type: boolean
type:
description: Type name
@@ -3437,6 +3477,11 @@ spec:
description: Use the S3 PutObject API, instead of the multipart
upload API.
type: boolean
+ Workers:
+ description: Specify number of worker threads to use to output
+ to S3
+ format: int32
+ type: integer
tls:
description: Fluent Bit provides integrated support for Transport
Layer Security (TLS) and it predecessor Secure Sockets Layer
@@ -3876,7 +3921,7 @@ spec:
description: Set resource types of data
type: string
resourceLabels:
- description: Optional list of comma seperated strings. Setting
+ description: Optional list of comma separated strings. Setting
these fields overrides the Stackdriver monitored resource API
values
items:
@@ -3958,6 +4003,10 @@ spec:
description: Identifier for a task within a namespace. Required
if Resource is generic_task
type: string
+ textPayloadKey:
+ description: The key used to select the text payload from the
+ record
+ type: string
workers:
description: Number of dedicated threads for the Stackdriver Output
Plugin
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterparsers.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterparsers.yaml
index 0e2983036e5..55f4e0d914a 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterparsers.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_clusterparsers.yaml
@@ -74,7 +74,20 @@ spec:
type: object
logfmt:
description: Logfmt defines logfmt parser configuration.
+ properties:
+ timeFormat:
+ description: Time_Format, eg. %Y-%m-%dT%H:%M:%S %z
+ type: string
+ timeKeep:
+ description: Time_Keep
+ type: boolean
+ timeKey:
+ description: Time_Key
+ type: string
type: object
+ x-kubernetes-validations:
+ - message: logfmt must not be null
+ rule: self != null
ltsv:
description: LTSV defines ltsv parser configuration.
properties:
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_collectors.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_collectors.yaml
index c99f8c00ad4..704bde01752 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_collectors.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_collectors.yaml
@@ -1502,6 +1502,10 @@ spec:
- verbs
type: object
type: array
+ replicas:
+ description: Replicas is the number of collector replicas to deploy
+ format: int32
+ type: integer
resources:
description: Compute Resources required by container.
properties:
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_filters.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_filters.yaml
index 55135835718..f21ee911c8e 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_filters.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_filters.yaml
@@ -85,7 +85,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -131,7 +131,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -279,6 +279,10 @@ spec:
Include Kubernetes namespace metadata only and no pod metadata.
If this is set, the values of Labels and Annotations are ignored.
type: boolean
+ ownerReferences:
+ description: Include Kubernetes owner references in the
+ extra metadata.
+ type: boolean
regexParser:
description: |-
Set an alternative Parser to process record Tag and extract pod_name, namespace_name, container_name and docker_id.
@@ -287,7 +291,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -313,6 +317,11 @@ spec:
instead of calling Kube Server API to enhance the log.
This could mitigate the Kube API heavy traffic issue for large cluster.
type: boolean
+ useTagForMeta:
+ description: If true, Kubernetes metadata (e.g., pod_name,
+ container_name, namespace_name etc) will be extracted
+ from the tag itself.
+ type: boolean
type: object
logToMetrics:
description: LogToMetrics defines a Log to Metrics Filter configuration.
@@ -387,7 +396,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -425,7 +434,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -548,7 +557,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -671,7 +680,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -711,7 +720,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -751,7 +760,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -788,7 +797,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -826,7 +835,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -864,7 +873,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
@@ -901,7 +910,7 @@ spec:
retryLimit:
description: 'RetryLimit describes how many times fluent-bit
should retry to send data to a specific output. If set
- to false fluent-bit will try indefinetly. If set to any
+ to false fluent-bit will try indefinitely. If set to any
integer N>0 it will try at most N+1 times. Leading zeros
are not allowed (values such as 007, 0150, 01 do not work).
If this property is not defined fluent-bit will use the
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbitconfigs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbitconfigs.yaml
index aafe67c640f..9a5ef6585db 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbitconfigs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_fluentbitconfigs.yaml
@@ -331,6 +331,10 @@ spec:
type: string
emitterStorageType:
type: string
+ enableChunkTrace:
+ description: Enable input/output tracing on debug images, controlled
+ more granualry via the http API
+ type: boolean
flushSeconds:
description: Interval to flush output
type: number
@@ -373,7 +377,7 @@ spec:
type: boolean
httpListen:
description: Address to listen
- pattern: ^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$
+ pattern: ^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(([A-Fa-f0-9:]+:+)+[A-Fa-f0-9]*)$
type: string
httpPort:
description: Port to listen
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_outputs.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_outputs.yaml
index 7da1e0b4203..97a511871ba 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_outputs.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_outputs.yaml
@@ -65,6 +65,18 @@ spec:
- appendblob
- blockblob
type: string
+ bufferingEnabled:
+ description: Enable buffering into disk before ingesting into
+ Azure Blob.
+ type: boolean
+ compressBlob:
+ description: 'Optional: Enables GZIP compression in the final
+ blockblob file. This option isn''t compatible when blob_type
+ = appendblob.'
+ enum:
+ - "on"
+ - "off"
+ type: string
containerName:
description: Name of the container that will contain the blobs
type: string
@@ -240,6 +252,18 @@ spec:
description: Hostname to be used for TLS SNI extension
type: string
type: object
+ uploadFileSize:
+ default: 200M
+ description: Specifies the size of files to be uploaded in MB.
+ Defaults to 200M.
+ type: string
+ uploadTimeout:
+ default: 30m
+ description: Optional. Specify a timeout for uploads. Fluent Bit
+ will start ingesting buffer files which have been created more
+ than x minutes ago and haven't reached upload_file_size limit
+ yet. Defaults to 30m.
+ type: string
required:
- accountName
- containerName
@@ -1981,7 +2005,7 @@ spec:
192.168.1.4:9092.'
type: string
dynamicTopic:
- description: adds unknown topics (found in Topic_Key) to Topics.
+ description: Adds unknown topics (found in Topic_Key) to Topics.
So in Topics only a default topic needs to be configured
type: boolean
format:
@@ -2067,6 +2091,7 @@ spec:
type: string
region:
description: The AWS region.
+ minLength: 1
type: string
roleARN:
description: ARN of an IAM role to assume (for cross account access).
@@ -2323,6 +2348,21 @@ spec:
items:
type: string
type: array
+ structuredMetadata:
+ additionalProperties:
+ type: string
+ description: |-
+ Stream structured metadata for API request. It can be multiple comma separated key=value pairs.
+ This is used for high cardinality data that isn't suited for using labels.
+ Only supported in Loki 3.0+ with schema v13 and TSDB storage.
+ type: object
+ structuredMetadataKeys:
+ description: |-
+ Optional list of record keys that will be placed as structured metadata.
+ This allows using record accessor patterns (e.g. $kubernetes['pod_name']) to reference record keys.
+ items:
+ type: string
+ type: array
tenantID:
description: |-
Tenant ID used by default to push logs to Loki.
@@ -2682,7 +2722,7 @@ spec:
type: integer
replaceDots:
description: When enabled, replace field name dots with underscore,
- required by Elasticsearch 2.0-2.3.
+ required by Opensearch 2.0-2.3.
type: boolean
suppressTypeName:
description: When enabled, mapping types is removed and Type option
@@ -2781,12 +2821,12 @@ spec:
for the current output logical destination.
type: string
traceError:
- description: When enabled print the elasticsearch API calls to
- stdout when elasticsearch returns an error
+ description: When enabled print the Opensearch API calls to stdout
+ when Opensearch returns an error
type: boolean
traceOutput:
- description: When enabled print the elasticsearch API calls to
- stdout (for diag only)
+ description: When enabled print the Opensearch API calls to stdout
+ (for diag only)
type: boolean
type:
description: Type name
@@ -3437,6 +3477,11 @@ spec:
description: Use the S3 PutObject API, instead of the multipart
upload API.
type: boolean
+ Workers:
+ description: Specify number of worker threads to use to output
+ to S3
+ format: int32
+ type: integer
tls:
description: Fluent Bit provides integrated support for Transport
Layer Security (TLS) and it predecessor Secure Sockets Layer
@@ -3876,7 +3921,7 @@ spec:
description: Set resource types of data
type: string
resourceLabels:
- description: Optional list of comma seperated strings. Setting
+ description: Optional list of comma separated strings. Setting
these fields overrides the Stackdriver monitored resource API
values
items:
@@ -3958,6 +4003,10 @@ spec:
description: Identifier for a task within a namespace. Required
if Resource is generic_task
type: string
+ textPayloadKey:
+ description: The key used to select the text payload from the
+ record
+ type: string
workers:
description: Number of dedicated threads for the Stackdriver Output
Plugin
diff --git a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_parsers.yaml b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_parsers.yaml
index 6bfe5e95284..1c117577242 100644
--- a/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_parsers.yaml
+++ b/pkg/component/observability/logging/fluentoperator/assets/crd-fluentbit.fluent.io_parsers.yaml
@@ -74,7 +74,20 @@ spec:
type: object
logfmt:
description: Logfmt defines logfmt parser configuration.
+ properties:
+ timeFormat:
+ description: Time_Format, eg. %Y-%m-%dT%H:%M:%S %z
+ type: string
+ timeKeep:
+ description: Time_Keep
+ type: boolean
+ timeKey:
+ description: Time_Key
+ type: string
type: object
+ x-kubernetes-validations:
+ - message: logfmt must not be null
+ rule: self != null
ltsv:
description: LTSV defines ltsv parser configuration.
properties:
From be49ff2e41643c1d735de889812c771513f69a44 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Mon, 10 Nov 2025 10:57:49 +0100
Subject: [PATCH 062/176] Update module github.com/containerd/containerd to v2
(#13311)
* Update module github.com/containerd/containerd to v2
* chore: Update containerd to v2.1.4
* chore: Adapt import paths for containerd/v2
* chore: Run `go mod tidy`
* chore: Import github.com/containerd/errdefs instead of full containerd/v1 module (PR review)
* chore: Run `go mod tidy`
---------
Co-authored-by: Marc Vornetran
---
go.mod | 36 ++++----
go.sum | 82 +++++++++----------
pkg/nodeagent/controller/healthcheck/add.go | 6 +-
.../controller/healthcheck/containerd.go | 2 +-
.../registry/containerd_extractor.go | 20 ++---
.../nodeagent/healthcheck/healthcheck_test.go | 2 +-
6 files changed, 72 insertions(+), 76 deletions(-)
diff --git a/go.mod b/go.mod
index 73870b6409e..58e043e227c 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,8 @@ require (
github.com/ahmetb/gen-crd-api-reference-docs v0.3.0
github.com/andybalholm/brotli v1.2.0
github.com/bramvdbogaerde/go-scp v1.5.0
- github.com/containerd/containerd v1.7.29
+ github.com/containerd/containerd/v2 v2.1.4
+ github.com/containerd/errdefs v1.0.0
github.com/coreos/go-systemd/v22 v22.6.0
github.com/distribution/distribution/v3 v3.0.0
github.com/docker/cli v28.5.2+incompatible
@@ -24,7 +25,7 @@ require (
github.com/gogo/protobuf v1.3.2
github.com/google/gnostic-models v0.7.0
github.com/google/go-cmp v0.7.0
- github.com/google/go-containerregistry v0.20.0
+ github.com/google/go-containerregistry v0.20.1
github.com/google/uuid v1.6.0
github.com/hashicorp/go-multierror v1.1.1
github.com/ironcore-dev/vgopath v0.1.5
@@ -90,13 +91,11 @@ require (
require (
cel.dev/expr v0.24.0 // indirect
dario.cat/mergo v1.0.2 // indirect
- github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
- github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
- github.com/Microsoft/hcsshim v0.11.7 // indirect
+ github.com/Microsoft/hcsshim v0.13.0 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/PaesslerAG/gval v1.2.4 // indirect
github.com/PaesslerAG/jsonpath v0.1.2-0.20240726212847-3a740cf7976f // indirect
@@ -108,16 +107,18 @@ require (
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
- github.com/containerd/cgroups v1.1.0 // indirect
- github.com/containerd/containerd/api v1.8.0 // indirect
- github.com/containerd/continuity v0.4.4 // indirect
- github.com/containerd/errdefs v0.3.0 // indirect
+ github.com/containerd/cgroups/v3 v3.0.5 // indirect
+ github.com/containerd/containerd v1.7.27 // indirect
+ github.com/containerd/containerd/api v1.9.0 // indirect
+ github.com/containerd/continuity v0.4.5 // indirect
+ github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/fifo v1.1.0 // indirect
github.com/containerd/log v0.1.0 // indirect
- github.com/containerd/platforms v0.2.1 // indirect
+ github.com/containerd/platforms v1.0.0-rc.1 // indirect
+ github.com/containerd/plugin v1.0.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
- github.com/containerd/typeurl/v2 v2.1.1 // indirect
+ github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
@@ -183,10 +184,10 @@ require (
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/spdystream v0.5.0 // indirect
- github.com/moby/sys/mountinfo v0.7.1 // indirect
- github.com/moby/sys/sequential v0.5.0 // indirect
- github.com/moby/sys/signal v0.7.0 // indirect
- github.com/moby/sys/user v0.3.0 // indirect
+ github.com/moby/sys/mountinfo v0.7.2 // indirect
+ github.com/moby/sys/sequential v0.6.0 // indirect
+ github.com/moby/sys/signal v0.7.1 // indirect
+ github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -197,8 +198,8 @@ require (
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/nexucis/lamenv v0.5.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
- github.com/opencontainers/runtime-spec v1.1.0 // indirect
- github.com/opencontainers/selinux v1.11.0 // indirect
+ github.com/opencontainers/runtime-spec v1.2.1 // indirect
+ github.com/opencontainers/selinux v1.12.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/perses/common v0.27.1-0.20250326140707-96e439b14e0e // indirect
github.com/perses/perses v0.51.0 // indirect
@@ -266,7 +267,6 @@ require (
golang.org/x/sys v0.37.0 // indirect
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect
golang.org/x/term v0.36.0 // indirect
- google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/grpc v1.76.0 // indirect
diff --git a/go.sum b/go.sum
index 3fcce88f487..a1b9dea6e15 100644
--- a/go.sum
+++ b/go.sum
@@ -14,7 +14,7 @@ cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/
cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU=
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
-cloud.google.com/go/compute v1.28.0 h1:OPtBxMcheSS+DWfci803qvPly3d4w7Eu5ztKBcFfzwk=
+cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
@@ -23,10 +23,8 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
-github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA=
-github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1 h1:DSDNVxqkoXJiko6x8a90zidoYqnYYa6c1MTzDKzKkTo=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1/go.mod h1:zGqV2R4Cr/k8Uye5w+dgQ06WJtEcbQG/8J7BB6hnCr4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys=
@@ -67,8 +65,8 @@ github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
-github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ=
-github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
+github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
+github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
@@ -131,28 +129,34 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls=
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
-github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
-github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
-github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE=
-github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
-github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
-github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
-github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
-github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
-github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
-github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
+github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
+github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
+github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII=
+github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0=
+github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
+github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
+github.com/containerd/containerd/v2 v2.1.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
+github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
+github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
+github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
+github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
+github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
+github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
+github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
-github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
-github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
+github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
+github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
+github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
+github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
-github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
-github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
+github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
+github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
@@ -335,7 +339,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -352,12 +355,11 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
-github.com/google/go-containerregistry v0.20.0 h1:wRqHpOeVh3DnenOrPy9xDOLdnLatiGuuNRVelR2gSbg=
-github.com/google/go-containerregistry v0.20.0/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
+github.com/google/go-containerregistry v0.20.1 h1:eTgx9QNYugV4DN5mz4U8hiAGTi1ybXn0TPi4Smd8du0=
+github.com/google/go-containerregistry v0.20.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -531,14 +533,14 @@ github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
-github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
-github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
-github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
-github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
-github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
-github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
-github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
-github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
+github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
+github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
+github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
+github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
+github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=
+github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8=
+github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
+github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
@@ -582,10 +584,10 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
-github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
-github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
-github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
+github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
+github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
+github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/openshift/api v0.0.0-20240124164020-e2ce40831f2e h1:cxgCNo/R769CO23AK5TCh45H9SMUGZ8RukiF2/Qif3o=
github.com/openshift/api v0.0.0-20240124164020-e2ce40831f2e/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
github.com/operator-framework/operator-lib v0.18.0 h1:6OaWemt/CuyrjFMkLyk4O8Vj4CPHxt/m1DMuMAmPwXo=
@@ -933,8 +935,6 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1017,8 +1017,6 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU=
-google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=
@@ -1043,8 +1041,6 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
diff --git a/pkg/nodeagent/controller/healthcheck/add.go b/pkg/nodeagent/controller/healthcheck/add.go
index 5b6747d13e0..55214859649 100644
--- a/pkg/nodeagent/controller/healthcheck/add.go
+++ b/pkg/nodeagent/controller/healthcheck/add.go
@@ -9,9 +9,9 @@ import (
"net"
"os"
- "github.com/containerd/containerd"
- "github.com/containerd/containerd/defaults"
- "github.com/containerd/containerd/namespaces"
+ containerd "github.com/containerd/containerd/v2/client"
+ "github.com/containerd/containerd/v2/defaults"
+ "github.com/containerd/containerd/v2/pkg/namespaces"
corev1 "k8s.io/api/core/v1"
"k8s.io/utils/clock"
"sigs.k8s.io/controller-runtime/pkg/builder"
diff --git a/pkg/nodeagent/controller/healthcheck/containerd.go b/pkg/nodeagent/controller/healthcheck/containerd.go
index 1bdcbf68968..aebd6b43494 100644
--- a/pkg/nodeagent/controller/healthcheck/containerd.go
+++ b/pkg/nodeagent/controller/healthcheck/containerd.go
@@ -9,7 +9,7 @@ import (
"fmt"
"time"
- "github.com/containerd/containerd"
+ containerd "github.com/containerd/containerd/v2/client"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/record"
"k8s.io/utils/clock"
diff --git a/pkg/nodeagent/registry/containerd_extractor.go b/pkg/nodeagent/registry/containerd_extractor.go
index 5631ed1b7b6..324fa225bf2 100644
--- a/pkg/nodeagent/registry/containerd_extractor.go
+++ b/pkg/nodeagent/registry/containerd_extractor.go
@@ -10,14 +10,14 @@ import (
"os"
"path"
- "github.com/containerd/containerd"
- "github.com/containerd/containerd/defaults"
- "github.com/containerd/containerd/errdefs"
- "github.com/containerd/containerd/mount"
- "github.com/containerd/containerd/namespaces"
- "github.com/containerd/containerd/remotes/docker"
- "github.com/containerd/containerd/remotes/docker/config"
- "github.com/containerd/containerd/snapshots"
+ containerd "github.com/containerd/containerd/v2/client"
+ "github.com/containerd/containerd/v2/core/mount"
+ "github.com/containerd/containerd/v2/core/remotes/docker"
+ "github.com/containerd/containerd/v2/core/remotes/docker/config"
+ "github.com/containerd/containerd/v2/core/snapshots"
+ "github.com/containerd/containerd/v2/defaults"
+ "github.com/containerd/containerd/v2/pkg/namespaces"
+ "github.com/containerd/errdefs"
"github.com/opencontainers/image-spec/identity"
"github.com/spf13/afero"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -61,12 +61,12 @@ func (e *containerdExtractor) CopyFromImage(ctx context.Context, imageRef string
Hosts: config.ConfigureHosts(ctx, config.HostOptions{HostDir: config.HostDirFromRoot("/etc/containerd/certs.d")}),
})
- image, err := client.Pull(ctx, imageRef, containerd.WithPullSnapshotter(containerd.DefaultSnapshotter), containerd.WithResolver(resolver), containerd.WithPullUnpack)
+ image, err := client.Pull(ctx, imageRef, containerd.WithPullSnapshotter(defaults.DefaultSnapshotter), containerd.WithResolver(resolver), containerd.WithPullUnpack)
if err != nil {
return fmt.Errorf("error pulling image: %w", err)
}
- snapshotter := client.SnapshotService(containerd.DefaultSnapshotter)
+ snapshotter := client.SnapshotService(defaults.DefaultSnapshotter)
imageMountDirectory, err := fs.TempDir(nodeagentconfigv1alpha1.TempDir, "mount-image-")
if err != nil {
diff --git a/test/integration/nodeagent/healthcheck/healthcheck_test.go b/test/integration/nodeagent/healthcheck/healthcheck_test.go
index d31bce5c4e8..3f4af4d0e42 100644
--- a/test/integration/nodeagent/healthcheck/healthcheck_test.go
+++ b/test/integration/nodeagent/healthcheck/healthcheck_test.go
@@ -13,7 +13,7 @@ import (
"net/http/httptest"
"time"
- "github.com/containerd/containerd"
+ containerd "github.com/containerd/containerd/v2/client"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
From ad41c362d46c9ef3b51ce60142bdef4650d20ef5 Mon Sep 17 00:00:00 2001
From: Vladimir Nachev
Date: Mon, 10 Nov 2025 13:04:42 +0200
Subject: [PATCH 063/176] [GEP-26] Update the proposal to depict how extensions
will use `WorkloadIdentity` (#13383)
* Update GEP-26 to depict how extensions will use WorkloadIdentity
* Apply review feedback
Co-authored-by: Dimitar Mirchev
---------
Co-authored-by: Dimitar Mirchev
---
docs/proposals/26-workload-identity.md | 85 +++++++++++++++++++-------
1 file changed, 62 insertions(+), 23 deletions(-)
diff --git a/docs/proposals/26-workload-identity.md b/docs/proposals/26-workload-identity.md
index aa4bc333726..7a4ecd2e498 100644
--- a/docs/proposals/26-workload-identity.md
+++ b/docs/proposals/26-workload-identity.md
@@ -225,7 +225,7 @@ of `SecretBinding`, but on top of that will be extended to refer to
In a nutshell, the changes introduced compared to `SecretBinding` are:
-- `CredentialsBinding.credentialsRef` field will be mutable. It will refer to a
+- `CredentialsBinding.credentialsRef` field will be immutable. It will refer to a
`WorkloadIdentity` or `Secret` resource by its name and namespace. If the
namespace is unset, the namespace of the `CredentialsBinding` will be used.
- `quotas` and `provider` fields have the semantic as their respective
@@ -271,38 +271,57 @@ cover clusters using WorkloadIdentity for authentication.
While the infrastructure credentials for the shoot cluster are the main driver
behind this GEP, various extensions can benefit of this feature as well. For
-this purpose, a new optional field named `workloadIdentity` will be introduced
-in `shoot.spec.extensions`, it will refer to workload identity by name assuming
-the workloadIdentity resource is in the namespace of the shoot. The seed CRD
-`extensions.extensions.gardener.cloud` will be also extended to reflect that the
-extension is using workload identity letting extension controllers know when a
-JWT or other kind of credentials are used.
-
-Similar approach can be taken to provide alternative to
-`shoot.spec.dns.providers.secretName`, e.g. a new field `workloadIdentity` will
-extended the `shoot.spec.dns.providers`.
+this purpose, `shoot.spec.resources` will be extended to allow `WorkloadIdentity`
+references next to the currently supported `Secret` and `ConfigMap`. Extensions,
+via their own `shoot.spec.extensions.providerConfig`, will specify which
+referenced resources they are using. This would allow extensions to reuse the
+same `WorkloadIdentity` without the need for multiple resource references. For
+every `WorkloadIdentity` referenced by the shoot, gardenlet will create a secret
+in the control plane namespace bearing the workload identity features - the token
+and the config. It will be up to the extension controller to make use of the
+workload identity credentials available in the secret. Similar approach will be
+taken to provide alternative to `shoot.spec.dns.providers.secretName`, e.g. a
+new field `credentialsRef` will extended the `shoot.spec.dns.providers`.
+Extension controllers are expected to implement admission validation for the
+`WorkloadIdentity` resources of the types that they support instead of relying
+on other extensions, i.e. infrastructure providers, to do the validation.
```yaml
spec:
extensions:
- type: some-extension
- workloadIdentity:
- name: foo
+ providerConfig:
+ apiVersion: some-extension.extensions.gardener.cloud/v1alpha1
+ kind: SomeExtensionConfig
+ resourcesRefs:
+ - name: resource-ref-1
dns:
providers:
- type: some-dns-provider
- workloadIdentity:
+ credentialsRef:
+ apiVersion: security.gardener.cloud/v1alpha1 # or "v1", when secret is being used
+ kind: WorkloadIdentity # or "Secret", when secret is being used
name: bar
+ resources:
+ - resourceName: resource-ref-1
+ apiVersion: security.gardener.cloud/v1alpha1 # or "v1", when secret is being used
+ kind: WorkloadIdentity # or "Secret", when secret is being used
+ name: bar
```
#### Seed API Related Changes
Wherever the Seed API is referring to secrets, it will be extended to refer to
workload identities, as of now these are the fields `spec.backup.` and
-`spec.dns.provider` and they will have new field `workloadIdentityRef` holding
-the name and the namespace of a workload identity resource. The respective
-`secretRef` fields will be made optional and validation will ensure only one of
-`secretRef` and `workloadIdentityRef` is used at a time.
+`spec.dns.provider` and they will have new field `credentialsRef` holding
+the object reference to a credentials resource - `v1.Secret` or
+`security.gardener.cloud/v1alpha1.WorkloadIdentity`. The respective
+`secretRef` fields will be deprecated and removed in favour of `credentialsRef`.
+During the migration phase, both fields will be allowed when the credential is
+of type `v1.Secret` and validation will ensure both refer to the same secret.
+
+The workload identity credentials will be made available to the controllers in
+the seed cluster via `Secret` containing the config and the token.
```yaml
apiVersion: core.gardener.cloud/v1beta1
@@ -311,14 +330,35 @@ metadata:
name: seed
spec:
backup:
- workloadIdentityRef:
+ credentialsRef:
+ apiVersion: security.gardener.cloud/v1alpha1 # or "v1", when secret is being used
+ kind: WorkloadIdentity # or "Secret", when secret is being used
name: backup-workloadidentity
namespace: garden
dns:
provider:
- workloadIdentityRef:
+ credentialsRef:
+ apiVersion: security.gardener.cloud/v1alpha1 # or "v1", when secret is being used
+ kind: WorkloadIdentity # or "Secret", when secret is being used
name: ingress-workloadidentity
namespace: garden
+ internal:
+ credentialsRef:
+ apiVersion: security.gardener.cloud/v1alpha1 # or "v1", when secret is being used
+ kind: WorkloadIdentity # or "Secret", when secret is being used
+ name: internal-workloadidentity
+ namespace: garden
+ defaults:
+ - credentialsRef:
+ apiVersion: security.gardener.cloud/v1alpha1 # or "v1", when secret is being used
+ kind: WorkloadIdentity # or "Secret", when secret is being used
+ name: default1-workloadidentity
+ namespace: garden
+ - credentialsRef:
+ apiVersion: security.gardener.cloud/v1alpha1 # or "v1", when secret is being used
+ kind: WorkloadIdentity # or "Secret", when secret is being used
+ name: default2-workloadidentity
+ namespace: garden
```
### Gardener as OIDC Token Issuer
@@ -482,9 +522,8 @@ type: Opaque
The secret `cloudprovider` that now holds the static credentials will be reused
to store the token and the provider config when the shoot is using workload
identity as infrastructure credentials. For each extension using workload
-identity, the secret will be named
-`workloadidentity-extension-`, and for dns providers
-`workloadidentity-dns-`.
+identity, the secret will be named as per the naming convention for referenced
+resources or other already established convention to name a secret in the seed.
The reconciliation flow for a component using workload identity tokens will look
like this:
From 46f49378a1a972e4ef2c75f42417d66b05b71588 Mon Sep 17 00:00:00 2001
From: Shafeeque E S
Date: Mon, 10 Nov 2025 18:17:46 +0530
Subject: [PATCH 064/176] Deploy `shoot-info` ConfigMap for workerless clusters
as well (#13386)
NB: Hide whitespace changes for this commit
---
pkg/component/shoot/system/system.go | 28 +++++----
pkg/component/shoot/system/system_test.go | 71 +++++++++++++----------
2 files changed, 58 insertions(+), 41 deletions(-)
diff --git a/pkg/component/shoot/system/system.go b/pkg/component/shoot/system/system.go
index 049a0d13204..9a724c5c222 100644
--- a/pkg/component/shoot/system/system.go
+++ b/pkg/component/shoot/system/system.go
@@ -174,14 +174,6 @@ func (s *shootSystem) computeResourcesData() (map[string][]byte, error) {
if !s.values.IsWorkerless {
var (
- shootInfoConfigMap = &corev1.ConfigMap{
- ObjectMeta: metav1.ObjectMeta{
- Name: v1beta1constants.ConfigMapNameShootInfo,
- Namespace: metav1.NamespaceSystem,
- },
- Data: s.shootInfoData(),
- }
-
port53 = intstr.FromInt32(53)
port443 = intstr.FromInt32(kubeapiserverconstants.Port)
port8053 = intstr.FromInt32(corednsconstants.PortServer)
@@ -299,7 +291,6 @@ func (s *shootSystem) computeResourcesData() (map[string][]byte, error) {
)
if err := registry.Add(
- shootInfoConfigMap,
networkPolicyAllowToShootAPIServer,
networkPolicyAllowToDNS,
networkPolicyAllowToKubelet,
@@ -313,6 +304,20 @@ func (s *shootSystem) computeResourcesData() (map[string][]byte, error) {
}
}
+ shootInfoConfigMap := &corev1.ConfigMap{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: v1beta1constants.ConfigMapNameShootInfo,
+ Namespace: metav1.NamespaceSystem,
+ },
+ Data: s.shootInfoData(),
+ }
+
+ if err := registry.Add(
+ shootInfoConfigMap,
+ ); err != nil {
+ return nil, err
+ }
+
if len(s.values.APIResourceList) > 0 {
if err := registry.Add(s.readOnlyClusterRole()); err != nil {
return nil, err
@@ -360,7 +365,6 @@ func (s *shootSystem) shootInfoData() map[string]string {
"provider": s.values.Object.Spec.Provider.Type,
"region": s.values.Object.Spec.Region,
"kubernetesVersion": s.values.Object.Spec.Kubernetes.Version,
- "podNetwork": s.values.PodNetworkCIDRs[0].String(),
"serviceNetwork": s.values.ServiceNetworkCIDRs[0].String(),
"maintenanceBegin": s.values.Object.Spec.Maintenance.TimeWindow.Begin,
"maintenanceEnd": s.values.Object.Spec.Maintenance.TimeWindow.End,
@@ -370,6 +374,10 @@ func (s *shootSystem) shootInfoData() map[string]string {
data["domain"] = *domain
}
+ if len(s.values.PodNetworkCIDRs) > 0 {
+ data["podNetwork"] = s.values.PodNetworkCIDRs[0].String()
+ }
+
if len(s.values.NodeNetworkCIDRs) > 0 {
data["nodeNetwork"] = s.values.NodeNetworkCIDRs[0].String()
}
diff --git a/pkg/component/shoot/system/system_test.go b/pkg/component/shoot/system/system_test.go
index 0803c652914..dcb56f5d0a4 100644
--- a/pkg/component/shoot/system/system_test.go
+++ b/pkg/component/shoot/system/system_test.go
@@ -151,48 +151,57 @@ var _ = Describe("ShootSystem", func() {
})
Context("shoot-info ConfigMap", func() {
+ var configMap *corev1.ConfigMap
+
+ BeforeEach(func() {
+ configMap = &corev1.ConfigMap{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "shoot-info",
+ Namespace: "kube-system",
+ },
+ Data: map[string]string{
+ "domain": domain,
+ "extensions": extension1 + `,` + extension2,
+ "kubernetesVersion": kubernetesVersion,
+ "maintenanceBegin": maintenanceBegin,
+ "maintenanceEnd": maintenanceEnd,
+ "nodeNetwork": nodeCIDRs[0].String(),
+ "nodeNetworks": nodeCIDRs[0].String() + "," + nodeCIDRs[1].String(),
+
+ "projectName": projectName,
+ "provider": providerType,
+ "region": region,
+ "serviceNetwork": serviceCIDRs[0].String(),
+ "serviceNetworks": serviceCIDRs[0].String() + "," + serviceCIDRs[1].String(),
+ "shootNamespace": projectNamespace,
+ "shootName": shootName,
+ },
+ }
+ })
+
+ It("should successfully deploy all resources", func() {
+ configMap.Data["podNetwork"] = podCIDRs[0].String()
+ configMap.Data["podNetworks"] = podCIDRs[0].String() + "," + podCIDRs[1].String()
+
+ Expect(managedResource).To(contain(configMap))
+ })
+
When("shoot is workerless", func() {
BeforeEach(func() {
values.IsWorkerless = true
+ values.PodNetworkCIDRs = nil
})
- It("should not deploy any ConfigMap", func() {
+ It("should successfully deploy all resources", func() {
manifests, err := test.ExtractManifestsFromManagedResourceData(managedResourceSecret.Data)
Expect(err).NotTo(HaveOccurred())
for _, manifest := range manifests {
- Expect(manifest).NotTo(And(ContainSubstring("name: shoot-info"), ContainSubstring("kind: ConfigMap")))
+ Expect(manifest).NotTo(ContainSubstring("podNetworks"))
}
- })
- })
- configMap := &corev1.ConfigMap{
- ObjectMeta: metav1.ObjectMeta{
- Name: "shoot-info",
- Namespace: "kube-system",
- },
- Data: map[string]string{
- "domain": domain,
- "extensions": extension1 + `,` + extension2,
- "kubernetesVersion": kubernetesVersion,
- "maintenanceBegin": maintenanceBegin,
- "maintenanceEnd": maintenanceEnd,
- "nodeNetwork": nodeCIDRs[0].String(),
- "nodeNetworks": nodeCIDRs[0].String() + "," + nodeCIDRs[1].String(),
- "podNetwork": podCIDRs[0].String(),
- "podNetworks": podCIDRs[0].String() + "," + podCIDRs[1].String(),
- "projectName": projectName,
- "provider": providerType,
- "region": region,
- "serviceNetwork": serviceCIDRs[0].String(),
- "serviceNetworks": serviceCIDRs[0].String() + "," + serviceCIDRs[1].String(),
- "shootNamespace": projectNamespace,
- "shootName": shootName,
- },
- }
-
- It("should successfully deploy all resources", func() {
- Expect(managedResource).To(contain(configMap))
+ Expect(managedResource).To(contain(configMap))
+ })
})
})
From bc3bc162eabac5ff7e4c407abef5a62711cd6b24 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Mon, 10 Nov 2025 13:47:57 +0100
Subject: [PATCH 065/176] Update dependency kyverno/kyverno to v1.16.0 (#13391)
---
example/provider-extensions/kyverno/kustomization.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/example/provider-extensions/kyverno/kustomization.yaml b/example/provider-extensions/kyverno/kustomization.yaml
index ad73a020620..fc5276abbce 100644
--- a/example/provider-extensions/kyverno/kustomization.yaml
+++ b/example/provider-extensions/kyverno/kustomization.yaml
@@ -2,7 +2,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
-- https://github.com/kyverno/kyverno/releases/download/v1.15.2/install.yaml
+- https://github.com/kyverno/kyverno/releases/download/v1.16.0/install.yaml
- kyverno-poddisruptionbudget.yaml
- kyverno-rbac.yaml
From b589ab7729ae48ed2417195ee7e29f5991d3b440 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Mon, 10 Nov 2025 15:32:44 +0100
Subject: [PATCH 066/176] Update module github.com/containerd/containerd/v2 to
v2.1.5 [SECURITY] (#13393)
---
go.mod | 2 +-
go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/go.mod b/go.mod
index 58e043e227c..4e3adca7610 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ require (
github.com/ahmetb/gen-crd-api-reference-docs v0.3.0
github.com/andybalholm/brotli v1.2.0
github.com/bramvdbogaerde/go-scp v1.5.0
- github.com/containerd/containerd/v2 v2.1.4
+ github.com/containerd/containerd/v2 v2.1.5
github.com/containerd/errdefs v1.0.0
github.com/coreos/go-systemd/v22 v22.6.0
github.com/distribution/distribution/v3 v3.0.0
diff --git a/go.sum b/go.sum
index a1b9dea6e15..51fad1549a7 100644
--- a/go.sum
+++ b/go.sum
@@ -135,8 +135,8 @@ github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFqu
github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0=
github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
-github.com/containerd/containerd/v2 v2.1.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
-github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
+github.com/containerd/containerd/v2 v2.1.5 h1:pWSmPxUszaLZKQPvOx27iD4iH+aM6o0BoN9+hg77cro=
+github.com/containerd/containerd/v2 v2.1.5/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
From 688a46f01daea633e4add06d8f7acb4237b2ba59 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 10 Nov 2025 14:32:54 +0000
Subject: [PATCH 067/176] Bump github.com/opencontainers/selinux from 1.12.0 to
1.13.0 (#13396)
Bumps [github.com/opencontainers/selinux](https://github.com/opencontainers/selinux) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/opencontainers/selinux/releases)
- [Commits](https://github.com/opencontainers/selinux/compare/v1.12.0...v1.13.0)
---
updated-dependencies:
- dependency-name: github.com/opencontainers/selinux
dependency-version: 1.13.0
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
go.mod | 5 +++--
go.sum | 10 ++++++----
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/go.mod b/go.mod
index 4e3adca7610..d684adc8e7b 100644
--- a/go.mod
+++ b/go.mod
@@ -90,6 +90,7 @@ require (
require (
cel.dev/expr v0.24.0 // indirect
+ cyphar.com/go-pathrs v0.2.1 // indirect
dario.cat/mergo v1.0.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
@@ -121,7 +122,7 @@ require (
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
- github.com/cyphar/filepath-securejoin v0.4.1 // indirect
+ github.com/cyphar/filepath-securejoin v0.6.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
@@ -199,7 +200,7 @@ require (
github.com/nexucis/lamenv v0.5.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/runtime-spec v1.2.1 // indirect
- github.com/opencontainers/selinux v1.12.0 // indirect
+ github.com/opencontainers/selinux v1.13.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/perses/common v0.27.1-0.20250326140707-96e439b14e0e // indirect
github.com/perses/perses v0.51.0 // indirect
diff --git a/go.sum b/go.sum
index 51fad1549a7..df00e20d502 100644
--- a/go.sum
+++ b/go.sum
@@ -20,6 +20,8 @@ cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCB
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
+cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
@@ -166,8 +168,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
-github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
-github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
+github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is=
+github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -586,8 +588,8 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
-github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
+github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84=
+github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s=
github.com/openshift/api v0.0.0-20240124164020-e2ce40831f2e h1:cxgCNo/R769CO23AK5TCh45H9SMUGZ8RukiF2/Qif3o=
github.com/openshift/api v0.0.0-20240124164020-e2ce40831f2e/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
github.com/operator-framework/operator-lib v0.18.0 h1:6OaWemt/CuyrjFMkLyk4O8Vj4CPHxt/m1DMuMAmPwXo=
From 7d954d12312bbc3f2415d7be0e018f643720c48c Mon Sep 17 00:00:00 2001
From: Marcel Boehm
Date: Mon, 10 Nov 2025 16:40:45 +0100
Subject: [PATCH 068/176] Build gardenadm image (#13394)
---
.github/workflows/build.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 5eea8b5d15d..709ae8ffdce 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -97,6 +97,9 @@ jobs:
- name: controller-manager
target: controller-manager
oci-repository: gardener/controller-manager
+ - name: gardenadm
+ target: gardenadm
+ oci-repository: gardener/gardenadm
- name: gardenlet
target: gardenlet
oci-repository: gardener/gardenlet
From 1f01c3b2d45746d24b74c780dc158becdb4b6931 Mon Sep 17 00:00:00 2001
From: Viktor
Date: Mon, 10 Nov 2025 18:38:43 +0200
Subject: [PATCH 069/176] Add `RadaBDimitrova` as core reviewer (#13347)
* Add RadaBDimitrova as core reviewer
* Add Rada as v1.147 release responsible
* fix table
---
OWNERS_ALIASES | 1 +
docs/development/process.md | 5 +++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 85367cb0cc7..7f64e0b4c79 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -25,6 +25,7 @@ aliases:
- marc1404
- oliver-goetz
- plkokanov
+ - RadaBDimitrova
- rfranzke
- ScheererJ
- shafeeqes
diff --git a/docs/development/process.md b/docs/development/process.md
index 6566337d4ea..8fd9c2139ea 100644
--- a/docs/development/process.md
+++ b/docs/development/process.md
@@ -25,9 +25,9 @@ Version | Week No | Begin Validation Phase | Due Date | Release Res
------- |------------| ---------------------- | -------------------|--------------------------------------------------------------|
v1.130 | Week 41-42 | October 6, 2025 | October 19, 2025 | [@vitanovs](https://github.com/vitanovs) |
v1.131 | Week 43-44 | October 20, 2025 | November 2, 2025 | [@dimitar-kostadinov](https://github.com/dimitar-kostadinov) |
-v1.132 | Week 45-46 | November 3, 2025 | November 16, 2025 | [@LucaBernstein](https://github.com/LucaBernstein) |
+v1.132 | Week 45-46 | November 3, 2025 | November 16, 2025 | [@LucaBernstein](https://github.com/LucaBernstein) |
v1.133 | Week 47-48 | November 17, 2025 | November 30, 2025 | [@ialidzhikov](https://github.com/ialidzhikov) |
-v1.134 | Week 49-50 | December 1, 2025 | December 14, 2025 | [@marc1404](https://github.com/marc1404) |
+v1.134 | Week 49-50 | December 1, 2025 | December 14, 2025 | [@marc1404](https://github.com/marc1404) |
v1.135 | Week 01-04 | December 29, 2025 | January 25, 2026 | [@timuthy](https://github.com/timuthy) |
v1.136 | Week 05-06 | January 26, 2026 | February 8, 2026 | [@ary1992](https://github.com/ary1992) |
v1.137 | Week 07-08 | February 9, 2026 | February 22, 2026 | [@acumino](https://github.com/acumino) |
@@ -40,6 +40,7 @@ v1.143 | Week 19-20 | May 4, 2026 | May 17, 2026 | [@shafeeqes
v1.144 | Week 21-22 | May 18, 2026 | May 31, 2026 | [@Kostov6](https://github.com/Kostov6) |
v1.145 | Week 23-24 | June 1, 2026 | June 14, 2026 | [@vitanovs](https://github.com/vitanovs) |
v1.146 | Week 25-26 | June 15, 2026 | June 28, 2026 | [@dimitar-kostadinov](https://github.com/dimitar-kostadinov) |
+v1.147 | Week 27-28 | June 29, 2026 | July 12, 2026 | [@RadaBDimitrova](https://github.com/RadaBDimitrova) |
Apart from the release of the next version, the release responsible is also taking care of potential hotfix releases of the last three minor versions.
The release responsible is the main contact person for coordinating new feature PRs for the next minor versions or cherry-pick PRs for the last three minor versions.
From ecbf549e962b64bd2555cc81dacaf39f7d4c7e30 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Mon, 10 Nov 2025 20:44:43 +0100
Subject: [PATCH 070/176] Update opentelemetry-operator to v0.139.0 (#13389)
---
go.mod | 2 +-
go.sum | 4 ++--
imagevector/containers.yaml | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/go.mod b/go.mod
index d684adc8e7b..300e77d4459 100644
--- a/go.mod
+++ b/go.mod
@@ -33,7 +33,7 @@ require (
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/onsi/ginkgo/v2 v2.27.1
github.com/onsi/gomega v1.38.2
- github.com/open-telemetry/opentelemetry-operator v0.138.0
+ github.com/open-telemetry/opentelemetry-operator v0.139.0
github.com/opencontainers/image-spec v1.1.1
github.com/pelletier/go-toml v1.9.5
github.com/perses/perses-operator v0.2.0
diff --git a/go.sum b/go.sum
index df00e20d502..e7c0e81ba9c 100644
--- a/go.sum
+++ b/go.sum
@@ -580,8 +580,8 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
-github.com/open-telemetry/opentelemetry-operator v0.138.0 h1:PWNLD3i+sGpPLV2HpTylgGXuJB7iZp4cpoGDtw2XTBo=
-github.com/open-telemetry/opentelemetry-operator v0.138.0/go.mod h1:RuM1oKvL0W9gNONH1mpV/1g08jGu7LugSl0BOkhuQhk=
+github.com/open-telemetry/opentelemetry-operator v0.139.0 h1:HD4ptH5NQDroxpBRPpMG3puPhCUVtKVAoHtVx6FRPPw=
+github.com/open-telemetry/opentelemetry-operator v0.139.0/go.mod h1:RuM1oKvL0W9gNONH1mpV/1g08jGu7LugSl0BOkhuQhk=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
diff --git a/imagevector/containers.yaml b/imagevector/containers.yaml
index 2c77224573c..c5beb248513 100644
--- a/imagevector/containers.yaml
+++ b/imagevector/containers.yaml
@@ -188,7 +188,7 @@ images:
- name: opentelemetry-operator
sourceRepository: github.com/open-telemetry/opentelemetry-operator
repository: europe-docker.pkg.dev/gardener-project/releases/3rd/opentelemetry-operator/opentelemetry-operator
- tag: "v0.138.0"
+ tag: "v0.139.0"
labels:
- name: 'gardener.cloud/cve-categorisation'
value:
From fec8de511b7ba382e168d758438a95d62af4d904 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 10 Nov 2025 19:44:50 +0000
Subject: [PATCH 071/176] Bump github.com/containerd/containerd from 1.7.27 to
1.7.29 (#13397)
Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.27 to 1.7.29.
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v1.7.27...v1.7.29)
---
updated-dependencies:
- dependency-name: github.com/containerd/containerd
dependency-version: 1.7.29
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
go.mod | 2 +-
go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/go.mod b/go.mod
index 300e77d4459..1d814eac17a 100644
--- a/go.mod
+++ b/go.mod
@@ -109,7 +109,7 @@ require (
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/cgroups/v3 v3.0.5 // indirect
- github.com/containerd/containerd v1.7.27 // indirect
+ github.com/containerd/containerd v1.7.29 // indirect
github.com/containerd/containerd/api v1.9.0 // indirect
github.com/containerd/continuity v0.4.5 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
diff --git a/go.sum b/go.sum
index e7c0e81ba9c..6bb67842b17 100644
--- a/go.sum
+++ b/go.sum
@@ -133,8 +133,8 @@ github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
-github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII=
-github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0=
+github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE=
+github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
github.com/containerd/containerd/v2 v2.1.5 h1:pWSmPxUszaLZKQPvOx27iD4iH+aM6o0BoN9+hg77cro=
From 615c59321f1688cfd72f58ce518d80abeeea4f10 Mon Sep 17 00:00:00 2001
From: Jeremy Rickards <9338170+rickardsjp@users.noreply.github.com>
Date: Mon, 10 Nov 2025 20:44:58 +0100
Subject: [PATCH 072/176] Adjust Istio Gateway dashboard to show correct
resource consumption (#13402)
* Update Istio dashboards to accurately reflect the total resource usage
Prior to this change, a bug with stacked graphs caused Plutono to show
only the resource usage of pods that were running at the end of the query
time range. For time ranges longer than the default 30m, this caused the
visual effect of istio ingressgateway resource consumption rising when pods
were replaced.
This commit removes the stacking and introduces a `_total` metric that
sums over all *selected* istio ingressgateway pods. It can still be hidden
by shift-clicking it in the legend below the graph.
* Update dashboard schema
---
.../istio-ingress-gateway-dashboard.json | 50 +++++++++++++------
1 file changed, 34 insertions(+), 16 deletions(-)
diff --git a/pkg/component/observability/plutono/dashboards/garden-seed/istio/istio-ingress-gateway-dashboard.json b/pkg/component/observability/plutono/dashboards/garden-seed/istio/istio-ingress-gateway-dashboard.json
index 52b2c0305d6..8b2bc9d6e6e 100644
--- a/pkg/component/observability/plutono/dashboards/garden-seed/istio/istio-ingress-gateway-dashboard.json
+++ b/pkg/component/observability/plutono/dashboards/garden-seed/istio/istio-ingress-gateway-dashboard.json
@@ -15,8 +15,7 @@
"editable": true,
"gnetId": null,
"graphTooltip": 0,
- "id": 23,
- "iteration": 1679041083994,
+ "iteration": 1762761234731,
"links": [],
"panels": [
{
@@ -58,15 +57,23 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.17",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
- "stack": true,
+ "stack": false,
"steppedLine": false,
"targets": [
+ {
+ "exemplar": true,
+ "expr": "sum(rate(container_cpu_usage_seconds_total{pod=~\"$istio_proxy_pod\"}[$__rate_interval]))",
+ "hide": false,
+ "interval": "",
+ "legendFormat": "_total",
+ "refId": "B"
+ },
{
"exemplar": true,
"expr": "rate(container_cpu_usage_seconds_total{pod=~\"$istio_proxy_pod\"}[$__rate_interval])",
@@ -161,15 +168,23 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.17",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
- "stack": true,
+ "stack": false,
"steppedLine": false,
"targets": [
+ {
+ "exemplar": true,
+ "expr": "sum(container_memory_working_set_bytes{pod=~\"istio-ingress.*\"})",
+ "hide": false,
+ "interval": "",
+ "legendFormat": "_total",
+ "refId": "A"
+ },
{
"exemplar": true,
"expr": "container_memory_working_set_bytes{pod=~\"$istio_proxy_pod\"}",
@@ -264,7 +279,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.17",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
@@ -367,7 +382,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.17",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
@@ -470,7 +485,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.17",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
@@ -573,7 +588,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.17",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
@@ -676,7 +691,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.17",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
@@ -780,7 +795,7 @@
"alertThreshold": true
},
"percentage": false,
- "pluginVersion": "7.5.17",
+ "pluginVersion": "7.5.43",
"pointradius": 5,
"points": false,
"renderer": "flot",
@@ -869,9 +884,13 @@
{
"allValue": null,
"current": {
- "selected": false,
- "text": "All",
- "value": "$__all"
+ "selected": true,
+ "text": [
+ "All"
+ ],
+ "value": [
+ "$__all"
+ ]
},
"datasource": "${datasource}",
"definition": "container_cpu_usage_seconds_total{container=\"istio-proxy\"}",
@@ -901,7 +920,6 @@
"allValue": null,
"current": {
"selected": true,
- "tags": [],
"text": [
"All"
],
From 7a923e1f5ee13335197a3e4cd7a0ee8543e0ef29 Mon Sep 17 00:00:00 2001
From: Plamen Kokanov <35485709+plkokanov@users.noreply.github.com>
Date: Mon, 10 Nov 2025 23:49:43 +0200
Subject: [PATCH 073/176] Add documentation on how to deprecate and remove
`Shoot` API fields (#13300)
* Add documentation on how to deprecate and remove `Shoot` API fields
* Address review comments
---
docs/development/changing-the-api.md | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/docs/development/changing-the-api.md b/docs/development/changing-the-api.md
index 3220dea6db8..4dd1b29b4d4 100644
--- a/docs/development/changing-the-api.md
+++ b/docs/development/changing-the-api.md
@@ -7,7 +7,7 @@ title: Changing the API
This document describes the steps that need to be performed when changing the API.
It provides guidance for API changes to both (Gardener system in general or component configurations).
-Generally, as Gardener is a Kubernetes-native extension, it follows the same API conventions and guidelines like Kubernetes itself. The Kubernetes
+Generally, as Gardener is a Kubernetes-native extension, it follows the same API conventions and guidelines like Kubernetes itself. The Kubernetes
[API Conventions](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md) as well as [Changing the API](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md) topics already provide a good overview and general explanation of the basic concepts behind it.
We are following the same approaches.
@@ -55,6 +55,30 @@ The steps for removing a field from the code base is:
Example of field removal can be found in the [Remove `seedTemplate` field from ManagedSeed API](https://github.com/gardener/gardener/pull/6972) PR.
+#### Additional Steps When Removing a Field From the Shoot API
+
+Removing fields from the `Shoot` API requires special handling because the removal is tied to specific Kubernetes versions and backwards compatibility must be maintained.
+When removing defaulted fields, extra care is needed because these fields already exist in storage even when users never explicitly set them.
+
+The deprecation and removal process takes two release cycles (three for defaulted fields):
+1. In the first release:
+ - Mark the field as deprecated.
+ - Remove all code that uses the field (or ensure controllers can handle `nil` values for defaulted fields).
+ - Forbid the field from being set for Kubernetes versions starting from the next minor version that will be supported by Gardener in a future release.
+ - Show a warning to users that the field is deprecated and will be forbidden after a specific Kubernetes version. Use the [`WarningsOnCreate`](https://github.com/gardener/gardener/blob/0bd160008f123cb268100f3316ef01d09c7fe84e/pkg/apiserver/registry/core/shoot/strategy.go#L207-L209) and [`WarningsOnUpdate`](https://github.com/gardener/gardener/blob/0bd160008f123cb268100f3316ef01d09c7fe84e/pkg/apiserver/registry/core/shoot/strategy.go#L211-L214) functions for this.
+ - Update the [maintenance reconciler](https://github.com/gardener/gardener/blob/0bd160008f123cb268100f3316ef01d09c7fe84e/pkg/controllermanager/controller/shoot/maintenance/reconciler.go) to set the field to `nil` during forced upgrades to Kubernetes versions where the field is forbidden.
+2. *For defaulted fields only, in a subsequent release:*
+ - Force the field to `nil` in the [`Canonicalize`](https://github.com/gardener/gardener/blob/0bd160008f123cb268100f3316ef01d09c7fe84e/pkg/apiserver/registry/core/shoot/strategy.go#L186-L190) function.
+ - Update the warning from step (1) to inform users that the field is being automatically set to `nil`.
+3. When Gardener drops support for the last Kubernetes version that allowed the deprecated field, remove the field completely from the API.
+
+This approach prevents several problems:
+ - Avoids issues when `gardener-apiserver` is upgraded to a version that sets fields to `nil` while other controllers are still running older versions.
+ - Allows users to update `Shoot`s using `Get` and `{Update,Patch}` requests without manually setting deprecated fields to `nil`, even when those fields were automatically defaulted in previous releases.
+ - Shows warnings when users explicitly set deprecated fields that will be automatically changed to `nil` by the [`Canonicalize`](https://github.com/gardener/gardener/blob/0bd160008f123cb268100f3316ef01d09c7fe84e/pkg/apiserver/registry/core/shoot/strategy.go#L186-L190) function. This warning is important because the update will increase the `Shoot`'s generation since the user's request (with the deprecated field set) differs from what is present in storage (where the field is `nil`).
+
+Examples for the above can be seen in the following PRs: [Deprecate CA flag `maxEmptyBulkDelete`](https://github.com/gardener/gardener/pull/12115), [Forbid setting the `Shoot`'s `.spec.kubernetes.clusterAutoscaler.maxEmptyBulkDelete` field for Kubernetes versions >= 1.33](https://github.com/gardener/gardener/pull/12413), and [Explicitly set `maxEmptyBulkDelete` to nil in `Canonicalize`](https://github.com/gardener/gardener/pull/13054)
+
## Component Configuration APIs
Most Gardener components have a component configuration that follows similar principles to the Gardener API.
From a000efea44203eb74cc14c49d75b8fde50e4b078 Mon Sep 17 00:00:00 2001
From: Tobias Schlicht <155947440+tobschli@users.noreply.github.com>
Date: Mon, 10 Nov 2025 22:49:50 +0100
Subject: [PATCH 074/176] [GEP-28] Update `gardenadm connect` docs (#13392)
* Add `make` target to build `gardenadm` locally
* Update `gardenadm connect` docs
* Implement PR feedback
Co-authored-by: Rafael Franzke
---------
Co-authored-by: Rafael Franzke
---
Makefile | 3 ++
.../getting_started_locally_with_gardenadm.md | 48 +++++++++++++++++--
2 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
index 3c5c917dd27..4f6f9d79243 100644
--- a/Makefile
+++ b/Makefile
@@ -426,6 +426,9 @@ operator-seed-up operator-seed-dev: $(SKAFFOLD) $(HELM) $(KUBECTL) operator-up g
TIMEOUT=900 ./hack/usage/wait-for.sh garden local VirtualGardenAPIServerAvailable RuntimeComponentsHealthy VirtualComponentsHealthy
operator-seed-down: $(SKAFFOLD) $(HELM) $(KUBECTL) seed-down garden-down
+# gardenadm
+gardenadm:
+ BUILD_OUTPUT_FILE=./bin/ BUILD_PACKAGES=./cmd/gardenadm $(MAKE) build
# gardenadm-{up,down}
gardenadm-%: export SKAFFOLD_FILENAME = skaffold-gardenadm.yaml
gardenadm-up: $(SKAFFOLD) $(KUBECTL)
diff --git a/docs/deployment/getting_started_locally_with_gardenadm.md b/docs/deployment/getting_started_locally_with_gardenadm.md
index 924190bcb95..d098ea84fdc 100644
--- a/docs/deployment/getting_started_locally_with_gardenadm.md
+++ b/docs/deployment/getting_started_locally_with_gardenadm.md
@@ -199,12 +199,52 @@ This will deploy [`gardener-operator`](../concepts/operator.md) and create a `Ga
Find all information about it [here](getting_started_locally.md#alternative-way-to-set-up-garden-and-seed-leveraging-gardener-operator).
Note, that in this setup, no `Seed` will be registered in the Gardener - it's just a plain garden cluster without the ability to create regular shoot clusters.
-Once above command is finished, you can connect the self-hosted shoot cluster to this Gardener instance:
+Once above command is finished, you can generate a bootstrap token using `gardenadm` to connect the shoot cluster to this Gardener instance.
+For this, you must have installed the `gardenadm` binary locally. You can build it via:
```shell
-$ kubectl -n gardenadm-unmanaged-infra exec -it machine-0 -- bash
-root@machine-0:/# gardenadm connect
-2025-07-03T12:21:49.586Z INFO Command is work in progress
+make gardenadm
+```
+
+This will install it to `./bin/gardenadm`, from where you can call it.
+
+After you have completed this, you need to get a kubeconfig for [the Gardener instance](../concepts/operator.md#accessing-the-virtual-garden-cluster) you want to connect the self-hosted shoot to.
+We will refer to the path of this kubeconfig as `` in the following.
+
+Now you can generate the bootstrap token and the full `gardenadm connect` command like this:
+
+```shell
+$ KUBECONFIG= ./bin/gardenadm token create --print-connect-command --shoot-namespace=garden --shoot-name=root
+# This will output a command similar to:
+gardenadm connect --bootstrap-token ... --ca-certificate ... https://api.virtual-garden.local.gardener.cloud
+```
+
+Copy the full output, exec once again into one of the control-plane machines of your self-hosted shoot cluster, and paste and run the generated `gardenadm connect` command there:
+
+```shell
+root@machine-0:/# gardenadm connect --bootstrap-token ... --ca-certificate ... https://api.virtual-garden.local.gardener.cloud
+2025-11-10T08:12:32.287Z INFO Using resources from directory {"configDir": "/gardenadm/resources/"}
+2025-11-10T08:12:32.334Z INFO Initializing gardenadm botanist with fake client set {"cloudProfile": {"apiVersion": "core.gardener.cloud/v1beta1", "kind": "CloudProfile", "name": "local"}, "project": {"apiVersion": "core.gardener.cloud/v1beta1", "kind": "Project", "name": "garden"}, "shoot": {"apiVersion": "core.gardener.cloud/v1beta1", "kind": "Shoot", "namespace": "garden", "name": "root"}}
+2025-11-10T08:12:32.345Z INFO Starting {"flow": "connect"}
+...
+2025-11-10T08:13:04.571Z INFO Succeeded {"flow": "connect", "task": "Waiting until gardenlet is ready"}
+2025-11-10T08:13:04.571Z INFO Finished {"flow": "connect"}
+```
+
+Once this is done, you can observe that there is now a `gardenlet` running in the self-hosted shoot cluster, which connects it to the Gardener instance:
+
+```shell
+root@machine-0:/# kubectl get pods -n kube-system | grep gardenlet
+gardenlet-6cbcb676f5-prh8f 1/1 Running 0 40m
+gardenlet-6cbcb676f5-wwn8w 1/1 Running 0 40m
+````
+
+You can also observe that the self-hosted shoot cluster is now registered as a shoot cluster in Gardener:
+
+```shell
+kubectl --kubeconfig= get Shoots -A
+NAMESPACE NAME CLOUDPROFILE PROVIDER REGION K8S VERSION HIBERNATION LAST OPERATION STATUS AGE
+garden root local local local 1.33.0 Awake healthy 42m
```
## Running E2E Tests for `gardenadm`
From 060533563b8cef47e066ea847e62284531747c40 Mon Sep 17 00:00:00 2001
From: Vladimir Nachev
Date: Tue, 11 Nov 2025 08:52:44 +0200
Subject: [PATCH 075/176] Add support for (local) multiplatform container
images build (#13324)
---
Dockerfile | 28 +++++++++++++++-------------
Makefile | 25 +++++++++++++------------
2 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index fd5b8ac0586..20b2db47831 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,77 +1,79 @@
# builder
-FROM golang:1.25.4 AS builder
+FROM --platform=$BUILDPLATFORM golang:1.25.4 AS builder
ARG GOPROXY=https://proxy.golang.org,direct
ENV GOPROXY=$GOPROXY
WORKDIR /go/src/github.com/gardener/gardener
COPY . .
ARG EFFECTIVE_VERSION
-RUN make install EFFECTIVE_VERSION=$EFFECTIVE_VERSION
+ARG TARGETOS
+ARG TARGETARCH
+RUN make build EFFECTIVE_VERSION=$EFFECTIVE_VERSION GOOS=$TARGETOS GOARCH=$TARGETARCH BUILD_OUTPUT_FILE="/output/bin/"
# distroless-static
FROM gcr.io/distroless/static-debian12:nonroot AS distroless-static
# apiserver
FROM distroless-static AS apiserver
-COPY --from=builder /go/bin/gardener-apiserver /gardener-apiserver
+COPY --from=builder /output/bin/gardener-apiserver /gardener-apiserver
WORKDIR /
ENTRYPOINT ["/gardener-apiserver"]
# controller-manager
FROM distroless-static AS controller-manager
-COPY --from=builder /go/bin/gardener-controller-manager /gardener-controller-manager
+COPY --from=builder /output/bin/gardener-controller-manager /gardener-controller-manager
WORKDIR /
ENTRYPOINT ["/gardener-controller-manager"]
# scheduler
FROM distroless-static AS scheduler
-COPY --from=builder /go/bin/gardener-scheduler /gardener-scheduler
+COPY --from=builder /output/bin/gardener-scheduler /gardener-scheduler
WORKDIR /
ENTRYPOINT ["/gardener-scheduler"]
# gardenlet
FROM distroless-static AS gardenlet
-COPY --from=builder /go/bin/gardenlet /gardenlet
+COPY --from=builder /output/bin/gardenlet /gardenlet
WORKDIR /
ENTRYPOINT ["/gardenlet"]
# gardenadm
FROM distroless-static AS gardenadm
-COPY --from=builder /go/bin/gardenadm /gardenadm
+COPY --from=builder /output/bin/gardenadm /gardenadm
WORKDIR /
ENTRYPOINT ["/gardenadm"]
# admission-controller
FROM distroless-static AS admission-controller
-COPY --from=builder /go/bin/gardener-admission-controller /gardener-admission-controller
+COPY --from=builder /output/bin/gardener-admission-controller /gardener-admission-controller
WORKDIR /
ENTRYPOINT ["/gardener-admission-controller"]
# resource-manager
FROM distroless-static AS resource-manager
-COPY --from=builder /go/bin/gardener-resource-manager /gardener-resource-manager
+COPY --from=builder /output/bin/gardener-resource-manager /gardener-resource-manager
WORKDIR /
ENTRYPOINT ["/gardener-resource-manager"]
# node-agent
FROM distroless-static AS node-agent
-COPY --from=builder /go/bin/gardener-node-agent /gardener-node-agent
+COPY --from=builder /output/bin/gardener-node-agent /gardener-node-agent
WORKDIR /
ENTRYPOINT ["/gardener-node-agent"]
# operator
FROM distroless-static AS operator
-COPY --from=builder /go/bin/gardener-operator /gardener-operator
+COPY --from=builder /output/bin/gardener-operator /gardener-operator
WORKDIR /
ENTRYPOINT ["/gardener-operator"]
# gardener-extension-provider-local
FROM distroless-static AS gardener-extension-provider-local
-COPY --from=builder /go/bin/gardener-extension-provider-local /gardener-extension-provider-local
+COPY --from=builder /output/bin/gardener-extension-provider-local /gardener-extension-provider-local
WORKDIR /
ENTRYPOINT ["/gardener-extension-provider-local"]
# gardener-extension-admission-local
FROM distroless-static AS gardener-extension-admission-local
-COPY --from=builder /go/bin/gardener-extension-admission-local /gardener-extension-admission-local
+COPY --from=builder /output/bin/gardener-extension-admission-local /gardener-extension-admission-local
WORKDIR /
ENTRYPOINT ["/gardener-extension-admission-local"]
diff --git a/Makefile b/Makefile
index 4f6f9d79243..6f4c2877141 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,7 @@ PARALLEL_E2E_TESTS ?= 5
GARDENER_RELEASE_DOWNLOAD_PATH := $(REPO_ROOT)/dev
DEV_SETUP_WITH_LPP_RESIZE_SUPPORT ?= false
DEV_SETUP_WITH_WORKLOAD_IDENTITY_SUPPORT ?= false
+TARGET_PLATFORMS ?= linux/$(shell go env GOARCH)
PRINT_HELP ?=
ifneq ($(SEED_NAME),provider-extensions)
@@ -91,18 +92,18 @@ build:
.PHONY: docker-images
docker-images:
- @echo "Building docker images with version and tag $(EFFECTIVE_VERSION)"
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(APISERVER_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(APISERVER_IMAGE_REPOSITORY):latest -f Dockerfile --target apiserver .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(CONTROLLER_MANAGER_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(CONTROLLER_MANAGER_IMAGE_REPOSITORY):latest -f Dockerfile --target controller-manager .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(SCHEDULER_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(SCHEDULER_IMAGE_REPOSITORY):latest -f Dockerfile --target scheduler .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(ADMISSION_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(ADMISSION_IMAGE_REPOSITORY):latest -f Dockerfile --target admission-controller .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(RESOURCE_MANAGER_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(RESOURCE_MANAGER_IMAGE_REPOSITORY):latest -f Dockerfile --target resource-manager .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(NODE_AGENT_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(NODE_AGENT_IMAGE_REPOSITORY):latest -f Dockerfile --target node-agent .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(OPERATOR_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(OPERATOR_IMAGE_REPOSITORY):latest -f Dockerfile --target operator .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(GARDENLET_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(GARDENLET_IMAGE_REPOSITORY):latest -f Dockerfile --target gardenlet .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(GARDENADM_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(GARDENADM_IMAGE_REPOSITORY):latest -f Dockerfile --target gardenadm .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(EXTENSION_PROVIDER_LOCAL_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(EXTENSION_PROVIDER_LOCAL_IMAGE_REPOSITORY):latest -f Dockerfile --target gardener-extension-provider-local .
- @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(EXTENSION_ADMISSION_LOCAL_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(EXTENSION_ADMISSION_LOCAL_IMAGE_REPOSITORY):latest -f Dockerfile --target gardener-extension-admission-local .
+ @echo "Building docker images with version and tag $(EFFECTIVE_VERSION) for target platforms $(TARGET_PLATFORMS)"
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(APISERVER_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(APISERVER_IMAGE_REPOSITORY):latest -f Dockerfile --target apiserver .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(CONTROLLER_MANAGER_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(CONTROLLER_MANAGER_IMAGE_REPOSITORY):latest -f Dockerfile --target controller-manager .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(SCHEDULER_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(SCHEDULER_IMAGE_REPOSITORY):latest -f Dockerfile --target scheduler .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(ADMISSION_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(ADMISSION_IMAGE_REPOSITORY):latest -f Dockerfile --target admission-controller .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(RESOURCE_MANAGER_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(RESOURCE_MANAGER_IMAGE_REPOSITORY):latest -f Dockerfile --target resource-manager .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(NODE_AGENT_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(NODE_AGENT_IMAGE_REPOSITORY):latest -f Dockerfile --target node-agent .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(OPERATOR_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(OPERATOR_IMAGE_REPOSITORY):latest -f Dockerfile --target operator .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(GARDENLET_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(GARDENLET_IMAGE_REPOSITORY):latest -f Dockerfile --target gardenlet .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(GARDENADM_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(GARDENADM_IMAGE_REPOSITORY):latest -f Dockerfile --target gardenadm .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(EXTENSION_PROVIDER_LOCAL_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(EXTENSION_PROVIDER_LOCAL_IMAGE_REPOSITORY):latest -f Dockerfile --target gardener-extension-provider-local .
+ @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) --platform $(TARGET_PLATFORMS) -t $(EXTENSION_ADMISSION_LOCAL_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) -t $(EXTENSION_ADMISSION_LOCAL_IMAGE_REPOSITORY):latest -f Dockerfile --target gardener-extension-admission-local .
.PHONY: docker-push
docker-push:
From 39c61c6cc75f1cdbdf0e299fd593fe363fa10b89 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Tue, 11 Nov 2025 07:52:51 +0100
Subject: [PATCH 076/176] Update module github.com/containerd/containerd/v2 to
v2.2.0 (#13400)
---
go.mod | 16 ++++++++--------
go.sum | 39 ++++++++++++++++++++-------------------
2 files changed, 28 insertions(+), 27 deletions(-)
diff --git a/go.mod b/go.mod
index 1d814eac17a..81f96642331 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ require (
github.com/ahmetb/gen-crd-api-reference-docs v0.3.0
github.com/andybalholm/brotli v1.2.0
github.com/bramvdbogaerde/go-scp v1.5.0
- github.com/containerd/containerd/v2 v2.1.5
+ github.com/containerd/containerd/v2 v2.2.0
github.com/containerd/errdefs v1.0.0
github.com/coreos/go-systemd/v22 v22.6.0
github.com/distribution/distribution/v3 v3.0.0
@@ -39,7 +39,7 @@ require (
github.com/perses/perses-operator v0.2.0
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.85.0
github.com/prometheus/blackbox_exporter v0.27.0
- github.com/prometheus/client_golang v1.23.0
+ github.com/prometheus/client_golang v1.23.2
github.com/prometheus/common v0.67.2
github.com/robfig/cron v1.2.0
github.com/spf13/afero v1.15.0
@@ -96,7 +96,7 @@ require (
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
- github.com/Microsoft/hcsshim v0.13.0 // indirect
+ github.com/Microsoft/hcsshim v0.14.0-rc.1 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/PaesslerAG/gval v1.2.4 // indirect
github.com/PaesslerAG/jsonpath v0.1.2-0.20240726212847-3a740cf7976f // indirect
@@ -108,20 +108,20 @@ require (
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
- github.com/containerd/cgroups/v3 v3.0.5 // indirect
+ github.com/containerd/cgroups/v3 v3.1.0 // indirect
github.com/containerd/containerd v1.7.29 // indirect
- github.com/containerd/containerd/api v1.9.0 // indirect
+ github.com/containerd/containerd/api v1.10.0 // indirect
github.com/containerd/continuity v0.4.5 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/fifo v1.1.0 // indirect
github.com/containerd/log v0.1.0 // indirect
- github.com/containerd/platforms v1.0.0-rc.1 // indirect
+ github.com/containerd/platforms v1.0.0-rc.2 // indirect
github.com/containerd/plugin v1.0.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
- github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
+ github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/cyphar/filepath-securejoin v0.6.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 // indirect
@@ -170,7 +170,7 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 // indirect
- github.com/klauspost/compress v1.18.0 // indirect
+ github.com/klauspost/compress v1.18.1 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labstack/echo/v4 v4.13.4 // indirect
github.com/labstack/gommon v0.4.2 // indirect
diff --git a/go.sum b/go.sum
index 6bb67842b17..723004333db 100644
--- a/go.sum
+++ b/go.sum
@@ -67,8 +67,8 @@ github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
-github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
-github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
+github.com/Microsoft/hcsshim v0.14.0-rc.1 h1:qAPXKwGOkVn8LlqgBN8GS0bxZ83hOJpcjxzmlQKxKsQ=
+github.com/Microsoft/hcsshim v0.14.0-rc.1/go.mod h1:hTKFGbnDtQb1wHiOWv4v0eN+7boSWAHyK/tNAaYZL0c=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
@@ -131,14 +131,14 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls=
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
-github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
-github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
+github.com/containerd/cgroups/v3 v3.1.0 h1:azxYVj+91ZgSnIBp2eI3k9y2iYQSR/ZQIgh9vKO+HSY=
+github.com/containerd/cgroups/v3 v3.1.0/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE=
github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
-github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
-github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
-github.com/containerd/containerd/v2 v2.1.5 h1:pWSmPxUszaLZKQPvOx27iD4iH+aM6o0BoN9+hg77cro=
-github.com/containerd/containerd/v2 v2.1.5/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
+github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o=
+github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM=
+github.com/containerd/containerd/v2 v2.2.0 h1:K7TqcXy+LnFmZaui2DgHsnp2gAHhVNWYaHlx7HXfys8=
+github.com/containerd/containerd/v2 v2.2.0/go.mod h1:YCMjKjA4ZA7egdHNi3/93bJR1+2oniYlnS+c0N62HdE=
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
@@ -149,8 +149,8 @@ github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
-github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
-github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
+github.com/containerd/platforms v1.0.0-rc.2 h1:0SPgaNZPVWGEi4grZdV8VRYQn78y+nm6acgLGv/QzE4=
+github.com/containerd/platforms v1.0.0-rc.2/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
@@ -164,8 +164,9 @@ github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03V
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
+github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
+github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is=
@@ -400,8 +401,8 @@ github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrR
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
-github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
-github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
+github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
+github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
@@ -475,8 +476,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
-github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
+github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
+github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -629,8 +630,8 @@ github.com/prometheus/blackbox_exporter v0.27.0/go.mod h1:X1tfplLxckV+1vPT0JF5q2
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
-github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
-github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
+github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
+github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -755,8 +756,8 @@ github.com/zitadel/oidc/v3 v3.38.1 h1:VTf1Bv/33UbSwJnIWbfEIdpUGYKfoHetuBNIqVTcjv
github.com/zitadel/oidc/v3 v3.38.1/go.mod h1:muukzAasaWmn3vBwEVMglJfuTE0PKCvLJGombPwXIRw=
github.com/zitadel/schema v1.3.1 h1:QT3kwiRIRXXLVAs6gCK/u044WmUVh6IlbLXUsn6yRQU=
github.com/zitadel/schema v1.3.1/go.mod h1:071u7D2LQacy1HAN+YnMd/mx1qVE2isb0Mjeqg46xnU=
-go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I=
-go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM=
+go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
+go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo=
go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk=
go.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0=
From 44af42b103578bf398b80a0c85ddd5ef6157909b Mon Sep 17 00:00:00 2001
From: Rafael Franzke
Date: Tue, 11 Nov 2025 10:43:44 +0100
Subject: [PATCH 077/176] [GEP-28] `gardenadm connect`: Introduce `shoot/lease`
controller in `gardenlet` (#13342)
* Prefactor: Rename constant for `GardenletReady` condition
We'll reuse it for `Shoot`s as well :)
* Move `seed/lease` controller into generic package
now in `pkg/gardenlet/controller/lease`
instead of `pkg/gardenlet/controller/seed/lease`
* Prefactor: Make `Lease` controller generic
* Add `Lease` controller for self-hosted `Shoot`s to `gardenlet`
* Adapt `Shoot{Authorizer,Restriction}` handlers
* Enable `shoot-lease` reconciler for self-hosted shoots
* Update `Processing` `Shoot` statuses to `Aborted`
- now that the `gardenlet` has permissions for `shoots/status` updates
- Also, filtering the seed names is no longer needed with https://github.com/gardener/gardener/blob/36c0959cec3c1145a36fbe98c335ed678d0aeb2d/cmd/gardenlet/app/app.go#L286-L288
* Enable periodic healthz check
* Adapt `seed-lifecycle` controller in GCM
Now it is the `gardenlet-lifecycle` controller reconciling both `Seed`s
and `Shoot`s.
* [GAPI] Maintain `shoot.gardener.cloud/is-self-hosted` label for better filtering
Without this, the `gardenlet-lifecycle` (and potential future actors)
would need to loop over all worker pools for each `Shoot`. This can
become quite costly in large landscapes - filtering via label selector
is fast and cheap.
* Address PR review feedback
* Address PR review feedback
* Address PR review feedback
---
cmd/gardenlet/app/app.go | 27 +--
docs/concepts/controller-manager.md | 26 +--
docs/concepts/gardenlet.md | 17 +-
.../admission/shootrestriction/handler.go | 29 +--
.../shootrestriction/handler_test.go | 150 ++++++++++++++
.../webhook/auth/seed/authorizer.go | 9 +-
.../webhook/auth/seed/authorizer_test.go | 38 ++++
.../webhook/auth/shoot/authorizer.go | 11 +-
.../webhook/auth/shoot/authorizer_test.go | 119 ++++++++++-
.../core/v1beta1/constants/types_constants.go | 2 +
pkg/apis/core/v1beta1/types_seed.go | 2 -
pkg/apis/core/v1beta1/types_utils.go | 3 +
pkg/apiserver/registry/core/shoot/strategy.go | 10 +
.../registry/core/shoot/strategy_test.go | 20 ++
.../garden/backupentry/backupentry.go | 2 +-
pkg/controllermanager/controller/add.go | 9 +
.../exposureclass/exposureclass_suite_test.go | 2 +-
.../controller/gardenletlifecycle/add.go | 79 ++++++++
.../controller/gardenletlifecycle/add_test.go | 77 ++++++++
.../gardenletlifecycle_suite_test.go | 17 ++
.../reconciler.go | 127 ++++++++----
.../controller/managedseedset/add_test.go | 6 +-
.../controller/managedseedset/replica.go | 2 +-
.../controller/managedseedset/replica_test.go | 2 +-
pkg/controllermanager/controller/seed/add.go | 7 -
.../controller/seed/lifecycle/add.go | 42 ----
.../controller/shoot/conditions/add_test.go | 4 +-
pkg/gardenlet/controller/add.go | 8 +-
pkg/gardenlet/controller/lease/add.go | 49 +++++
.../{seed => }/lease/lease_suite_test.go | 0
pkg/gardenlet/controller/lease/reconciler.go | 142 +++++++++++++
.../{seed => }/lease/reconciler_test.go | 48 ++---
pkg/gardenlet/controller/seed/add.go | 8 +-
pkg/gardenlet/controller/seed/lease/add.go | 66 +++----
.../controller/seed/lease/reconciler.go | 132 -------------
.../controller/seed/seed/reconciler.go | 2 +-
pkg/gardenlet/controller/shoot/add.go | 10 +
pkg/gardenlet/controller/shoot/lease/add.go | 38 ++++
pkg/scheduler/controller/shoot/reconciler.go | 2 +-
.../controller/shoot/reconciler_test.go | 10 +-
pkg/utils/graph/eventhandler_seed.go | 2 +-
pkg/utils/graph/eventhandler_shoot.go | 10 +-
pkg/utils/graph/graph_test.go | 76 ++++---
pkg/utils/kubernetes/health/seed.go | 2 +-
pkg/utils/kubernetes/health/seed_test.go | 22 +--
.../global/customverbauthorizer/admission.go | 4 +-
skaffold-gardenadm.yaml | 2 +
skaffold-operator.yaml | 2 +-
skaffold-seed.yaml | 2 +
skaffold.yaml | 4 +-
test/framework/k8s_utils_test.go | 2 +-
.../lifecycle_suite_test.go | 23 ++-
.../lifecycle_test.go | 6 +-
.../managedseedset/managedseedset_test.go | 2 +-
.../shoot/conditions/conditions_test.go | 12 +-
.../shoot/migration/migration_test.go | 2 +-
.../gardenlet/seed/lease/lease_suite_test.go | 13 +-
.../gardenlet/seed/lease/lease_test.go | 160 ++++++++-------
.../gardenlet/shoot/lease/lease_suite_test.go | 187 ++++++++++++++++++
.../gardenlet/shoot/lease/lease_test.go | 124 ++++++++++++
.../integration/scheduler/shoot/shoot_test.go | 2 +-
61 files changed, 1502 insertions(+), 511 deletions(-)
create mode 100644 pkg/controllermanager/controller/gardenletlifecycle/add.go
create mode 100644 pkg/controllermanager/controller/gardenletlifecycle/add_test.go
create mode 100644 pkg/controllermanager/controller/gardenletlifecycle/gardenletlifecycle_suite_test.go
rename pkg/controllermanager/controller/{seed/lifecycle => gardenletlifecycle}/reconciler.go (54%)
delete mode 100644 pkg/controllermanager/controller/seed/lifecycle/add.go
create mode 100644 pkg/gardenlet/controller/lease/add.go
rename pkg/gardenlet/controller/{seed => }/lease/lease_suite_test.go (100%)
create mode 100644 pkg/gardenlet/controller/lease/reconciler.go
rename pkg/gardenlet/controller/{seed => }/lease/reconciler_test.go (88%)
delete mode 100644 pkg/gardenlet/controller/seed/lease/reconciler.go
create mode 100644 pkg/gardenlet/controller/shoot/lease/add.go
rename test/integration/controllermanager/{seed/lifecycle => gardenletlifecycle}/lifecycle_suite_test.go (89%)
rename test/integration/controllermanager/{seed/lifecycle => gardenletlifecycle}/lifecycle_test.go (98%)
create mode 100644 test/integration/gardenlet/shoot/lease/lease_suite_test.go
create mode 100644 test/integration/gardenlet/shoot/lease/lease_test.go
diff --git a/cmd/gardenlet/app/app.go b/cmd/gardenlet/app/app.go
index a9cde085cc4..0ebde01e40a 100644
--- a/cmd/gardenlet/app/app.go
+++ b/cmd/gardenlet/app/app.go
@@ -173,14 +173,8 @@ func run(ctx context.Context, cancel context.CancelFunc, log logr.Logger, cfg *g
if err := mgr.AddReadyzCheck("runtime-informer-sync", gardenerhealthz.NewCacheSyncHealthz(mgr.GetCache())); err != nil {
return err
}
-
- if !gardenlet.IsResponsibleForSelfHostedShoot() {
- // TODO(rfranzke): This healthz check is currently not enabled for self-hosted shoots because it depends on the
- // seed-lease controller. This controller is currently not enabled, but it will be in the future. Once it is
- // enabled, we can also enable this healthz check for self-hosted shoots.
- if err := mgr.AddHealthzCheck("periodic-health", gardenerhealthz.CheckerFunc(healthManager)); err != nil {
- return err
- }
+ if err := mgr.AddHealthzCheck("periodic-health", gardenerhealthz.CheckerFunc(healthManager)); err != nil {
+ return err
}
var selfHostedShootMeta *types.NamespacedName
@@ -368,6 +362,10 @@ func (g *garden) Start(ctx context.Context) error {
Field: fields.SelectorFromSet(fields.Set{metav1.ObjectNameField: gardenlet.ResourcePrefixSelfHostedShoot + g.selfHostedShootMeta.Name}),
Namespaces: map[string]cache.Config{g.selfHostedShootMeta.Namespace: {}},
},
+ &coordinationv1.Lease{}: {
+ Field: fields.SelectorFromSet(fields.Set{metav1.ObjectNameField: gardenlet.ResourcePrefixSelfHostedShoot + g.selfHostedShootMeta.Name}),
+ Namespaces: map[string]cache.Config{g.selfHostedShootMeta.Namespace: {}},
+ },
}
return kubernetes.AggregatorCacheFunc(
@@ -424,12 +422,11 @@ func (g *garden) Start(ctx context.Context) error {
if err := g.registerSeed(ctx, gardenCluster.GetClient()); err != nil {
return err
}
+ }
- // TODO(rfranzke): Move this out of this 'if'-condition once the "shoot gardenlets" have the needed permissions.
- log.Info("Updating last operation status of processing Shoots to 'Aborted'")
- if err := g.updateProcessingShootStatusToAborted(ctx, gardenCluster.GetClient()); err != nil {
- return err
- }
+ log.Info("Updating last operation status of processing Shoots to 'Aborted'")
+ if err := g.updateProcessingShootStatusToAborted(ctx, gardenCluster.GetClient()); err != nil {
+ return err
}
log.Info("Attempt to create seedmanagement.gardener.cloud/v1alpha1.Gardenlet object in garden cluster for self-upgrades if necessary")
@@ -690,10 +687,6 @@ func (g *garden) updateProcessingShootStatusToAborted(ctx context.Context, garde
var taskFns []flow.TaskFn
for _, shoot := range shootList.Items {
- if specSeedName, statusSeedName := gardenerutils.GetShootSeedNames(&shoot); gardenerutils.GetResponsibleSeedName(specSeedName, statusSeedName) != g.config.SeedConfig.Name {
- continue
- }
-
// Check if the status indicates that an operation is processing and mark it as "aborted".
if shoot.Status.LastOperation == nil || shoot.Status.LastOperation.State != gardencorev1beta1.LastOperationStateProcessing {
continue
diff --git a/docs/concepts/controller-manager.md b/docs/concepts/controller-manager.md
index d6e3ca1f6c3..50d62ea2213 100644
--- a/docs/concepts/controller-manager.md
+++ b/docs/concepts/controller-manager.md
@@ -162,6 +162,19 @@ In order to activate it, provide the following configuration:
Consequently, to ensure that `ExposureClass`es in-use are always present in the system until the last referring `Shoot` gets deleted, the controller adds a finalizer which is only released when there is no `Shoot` referencing the `ExposureClass` anymore.
+### [Gardenlet Lifecycle Controller](../../pkg/controllermanager/controller/gardenletlifecycle)
+
+The "Lifecycle" reconciler processes `Seed` and self-hosted `Shoot` objects which are enqueued every 10 seconds in order to check if the responsible
+`gardenlet` is still responding and operable. Therefore, it checks renewals via `Lease` objects in the garden cluster
+which are renewed regularly by the `gardenlet`.
+
+In case a `Lease` is not renewed for the configured amount in `config.controllers.seed.monitorPeriod.duration`:
+
+1. The reconciler assumes that the `gardenlet` stopped operating and updates the `GardenletReady` condition to `Unknown`.
+2. Additionally, the conditions and constraints of all affected `Shoot` resources are set to `Unknown` as well,
+ because a striking `gardenlet` won't be able to maintain these conditions anymore.
+3. For `Seed`s: If the gardenlet's client certificate has expired (identified based on the `.status.clientCertificateExpirationTimestamp` field in the `Seed` resource) and if it is managed by a `ManagedSeed`, then this will be triggered for a reconciliation. This will trigger the bootstrapping process again and allows gardenlets to obtain a fresh client certificate.
+
### [`ManagedSeedSet` Controller](../../pkg/controllermanager/controller/managedseedset)
`ManagedSeedSet` objects maintain a stable set of replicas of `ManagedSeed`s, i.e. they guarantee the availability of a specified number of identical `ManagedSeed`s on an equal number of identical `Shoot`s.
@@ -321,19 +334,6 @@ This reconciler reconciles `Seed` objects and checks whether all `ControllerInst
Concretely, all three conditions `Valid`, `Installed`, and `Healthy` must have status `True` and the `Progressing` condition must have status `False`.
Based on this check, it maintains the `ExtensionsReady` condition in the respective `Seed`'s `.status.conditions` list.
-#### ["Lifecycle" Reconciler](../../pkg/controllermanager/controller/seed/lifecycle)
-
-The "Lifecycle" reconciler processes `Seed` objects which are enqueued every 10 seconds in order to check if the responsible
-`gardenlet` is still responding and operable. Therefore, it checks renewals via `Lease` objects of the seed in the garden cluster
-which are renewed regularly by the `gardenlet`.
-
-In case a `Lease` is not renewed for the configured amount in `config.controllers.seed.monitorPeriod.duration`:
-
-1. The reconciler assumes that the `gardenlet` stopped operating and updates the `GardenletReady` condition to `Unknown`.
-2. Additionally, the conditions and constraints of all `Shoot` resources scheduled on the affected seed are set to `Unknown` as well,
- because a striking `gardenlet` won't be able to maintain these conditions any more.
-3. If the gardenlet's client certificate has expired (identified based on the `.status.clientCertificateExpirationTimestamp` field in the `Seed` resource) and if it is managed by a `ManagedSeed`, then this will be triggered for a reconciliation. This will trigger the bootstrapping process again and allows gardenlets to obtain a fresh client certificate.
-
#### ["Reference" Reconciler](../../pkg/controllermanager/controller/seed/reference)
Seed objects may specify references to other objects in the `garden` namespace in the garden cluster which are required for certain features.
diff --git a/docs/concepts/gardenlet.md b/docs/concepts/gardenlet.md
index e774a703786..8b502fa966b 100644
--- a/docs/concepts/gardenlet.md
+++ b/docs/concepts/gardenlet.md
@@ -177,7 +177,8 @@ the gardenlet is using `Lease` objects for heart beats of the seed cluster.
Every two seconds, the gardenlet checks that the seed cluster's `/healthz`
endpoint returns HTTP status code 200.
If that is the case, the gardenlet renews the lease in the Garden cluster in the `gardener-system-seed-lease` namespace and updates
-the `GardenletReady` condition in the `status.conditions` field of the `Seed` resource. For more information, see [this section](#lease-reconciler).
+the `GardenletReady` condition in the `status.conditions` field of the `Seed` resource.
+For more information, see [this section](#lease-reconciler).
Similar to the `node-lifecycle-controller` inside the `kube-controller-manager`,
the `gardener-controller-manager` features a `seed-lifecycle-controller` that sets
@@ -486,6 +487,20 @@ A pod is considered stale when:
- it was terminated with reason `NodeAffinity`.
- it is stuck in termination (i.e., if its `deletionTimestamp` is more than `5m` ago).
+#### ["Lease" Reconciler](../../pkg/gardenlet/controller/shoot/lease)
+
+This reconciler is only enabled for self-hosted shoot clusters.
+It checks whether the connection to the shoot cluster's `/healthz` endpoint works.
+If this succeeds, then it renews a `Lease` resource in the garden cluster in the same namespace as the `Shoot` the `gardenlet` is responsible for.
+This indicates a heartbeat to the external world, and internally the `gardenlet` sets its health status to `true`.
+In addition, the `GardenletReady` condition in the `status` of the `Shoot` is set to `True`.
+The whole process is similar to what the `kubelet` does to report heartbeats for its `Node` resource and its `KubeletReady` condition.
+For more information, see [this section](#heartbeats).
+
+If the connection to the `/healthz` endpoint or the update of the `Lease` fails, then the internal health status of `gardenlet` is set to `false`.
+Also, this internal health status is set to `false` automatically after some time, in case the controller gets stuck for whatever reason.
+This internal health status is available via the `gardenlet`'s `/healthz` endpoint and is used for the `livenessProbe` in the `gardenlet` pod.
+
#### ["State" Reconciler](../../pkg/gardenlet/controller/shoot/state)
This reconciler periodically (default: every `6h`) performs backups of the state of `Shoot` clusters and persists them into `ShootState` resources into the same namespace as the `Shoot`s in the garden cluster.
diff --git a/pkg/admissioncontroller/webhook/admission/shootrestriction/handler.go b/pkg/admissioncontroller/webhook/admission/shootrestriction/handler.go
index a51d28963d9..354257c635a 100644
--- a/pkg/admissioncontroller/webhook/admission/shootrestriction/handler.go
+++ b/pkg/admissioncontroller/webhook/admission/shootrestriction/handler.go
@@ -14,6 +14,7 @@ import (
"github.com/go-logr/logr"
admissionv1 "k8s.io/api/admission/v1"
certificatesv1 "k8s.io/api/certificates/v1"
+ coordinationv1 "k8s.io/api/coordination/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -34,6 +35,7 @@ var (
// group and the resource (but it ignores the version).
certificateSigningRequestResource = certificatesv1.Resource("certificatesigningrequests")
gardenletResource = seedmanagementv1alpha1.Resource("gardenlets")
+ leaseResource = coordinationv1.Resource("leases")
projectResource = gardencorev1beta1.Resource("projects")
shootResource = gardencorev1beta1.Resource("shoots")
)
@@ -67,7 +69,10 @@ func (h *Handler) Handle(_ context.Context, request admission.Request) admission
return h.admitCertificateSigningRequest(gardenletShootInfo, userType, request)
case gardenletResource:
- return h.admitGardenlet(gardenletShootInfo, request)
+ return h.admitCreateWithResourcePrefix(gardenletShootInfo, request)
+
+ case leaseResource:
+ return h.admitCreateWithResourcePrefix(gardenletShootInfo, request)
default:
log.Info(
@@ -108,23 +113,23 @@ func (h *Handler) admitCertificateSigningRequest(gardenletShootInfo types.Namesp
return h.admit(gardenletShootInfo, types.NamespacedName{Name: name, Namespace: namespace})
}
-func (h *Handler) admitGardenlet(gardenletShootInfo types.NamespacedName, request admission.Request) admission.Response {
+func (h *Handler) admit(gardenletShootInfo, objectShootInfo types.NamespacedName) admission.Response {
+ // Allow request if the shoot the gardenlet is responsible for matches with the shoot related to the object.
+ if gardenletShootInfo.Name == objectShootInfo.Name && gardenletShootInfo.Namespace == objectShootInfo.Namespace {
+ return admission.Allowed("")
+ }
+
+ return admission.Errored(http.StatusForbidden, fmt.Errorf("object does not belong to shoot %s", gardenletShootInfo))
+}
+
+func (h *Handler) admitCreateWithResourcePrefix(gardenletShootInfo types.NamespacedName, request admission.Request) admission.Response {
if request.Operation != admissionv1.Create {
return admission.Errored(http.StatusBadRequest, fmt.Errorf("unexpected operation: %q", request.Operation))
}
if !strings.HasPrefix(request.Name, gardenletutils.ResourcePrefixSelfHostedShoot) {
- return admission.Errored(http.StatusBadRequest, fmt.Errorf("the Gardenlet resources for self-hosted shoots must be prefixed with %q", gardenletutils.ResourcePrefixSelfHostedShoot))
+ return admission.Errored(http.StatusBadRequest, fmt.Errorf("the resource for self-hosted shoots must be prefixed with %q", gardenletutils.ResourcePrefixSelfHostedShoot))
}
return h.admit(gardenletShootInfo, types.NamespacedName{Name: strings.TrimPrefix(request.Name, gardenletutils.ResourcePrefixSelfHostedShoot), Namespace: request.Namespace})
}
-
-func (h *Handler) admit(gardenletShootInfo, objectShootInfo types.NamespacedName) admission.Response {
- // Allow request if the shoot the gardenlet is responsible for matches with the shoot related to the object.
- if gardenletShootInfo.Name == objectShootInfo.Name && gardenletShootInfo.Namespace == objectShootInfo.Namespace {
- return admission.Allowed("")
- }
-
- return admission.Errored(http.StatusForbidden, fmt.Errorf("object does not belong to shoot %s", gardenletShootInfo))
-}
diff --git a/pkg/admissioncontroller/webhook/admission/shootrestriction/handler_test.go b/pkg/admissioncontroller/webhook/admission/shootrestriction/handler_test.go
index e11e6191642..117fca007db 100644
--- a/pkg/admissioncontroller/webhook/admission/shootrestriction/handler_test.go
+++ b/pkg/admissioncontroller/webhook/admission/shootrestriction/handler_test.go
@@ -16,6 +16,7 @@ import (
admissionv1 "k8s.io/api/admission/v1"
authenticationv1 "k8s.io/api/authentication/v1"
certificatesv1 "k8s.io/api/certificates/v1"
+ coordinationv1 "k8s.io/api/coordination/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
@@ -25,6 +26,7 @@ import (
. "github.com/gardener/gardener/pkg/admissioncontroller/webhook/admission/shootrestriction"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1"
"github.com/gardener/gardener/pkg/client/kubernetes"
"github.com/gardener/gardener/pkg/logger"
mockcache "github.com/gardener/gardener/third_party/mock/controller-runtime/cache"
@@ -274,6 +276,154 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
})
})
})
+
+ Context("when requested for Gardenlets", func() {
+ var name string
+
+ BeforeEach(func() {
+ name = "self-hosted-shoot-foo"
+
+ request.Name = name
+ request.UserInfo = gardenletUser
+ request.Resource = metav1.GroupVersionResource{
+ Group: seedmanagementv1alpha1.SchemeGroupVersion.Group,
+ Version: seedmanagementv1alpha1.SchemeGroupVersion.Version,
+ Resource: "gardenlets",
+ }
+ })
+
+ DescribeTable("should not allow the request because no allowed verb",
+ func(operation admissionv1.Operation) {
+ request.Operation = operation
+
+ Expect(handler.Handle(ctx, request)).To(Equal(admission.Response{
+ AdmissionResponse: admissionv1.AdmissionResponse{
+ Allowed: false,
+ Result: &metav1.Status{
+ Code: int32(http.StatusBadRequest),
+ Message: fmt.Sprintf("unexpected operation: %q", operation),
+ },
+ },
+ }))
+ },
+
+ Entry("update", admissionv1.Update),
+ Entry("delete", admissionv1.Delete),
+ )
+
+ Context("when operation is create", func() {
+ BeforeEach(func() {
+ request.Operation = admissionv1.Create
+ })
+
+ It("should return an error because resource name is not prefixed", func() {
+ request.Name = "foo"
+
+ Expect(handler.Handle(ctx, request)).To(Equal(admission.Response{
+ AdmissionResponse: admissionv1.AdmissionResponse{
+ Allowed: false,
+ Result: &metav1.Status{
+ Code: int32(http.StatusBadRequest),
+ Message: `the resource for self-hosted shoots must be prefixed with "self-hosted-shoot-"`,
+ },
+ },
+ }))
+ })
+
+ It("should return an error because the requestor is not responsible for the resource", func() {
+ Expect(handler.Handle(ctx, request)).To(Equal(admission.Response{
+ AdmissionResponse: admissionv1.AdmissionResponse{
+ Allowed: false,
+ Result: &metav1.Status{
+ Code: int32(http.StatusForbidden),
+ Message: "object does not belong to shoot " + shootNamespace + "/" + shootName,
+ },
+ },
+ }))
+ })
+
+ It("should return success because the requestor is responsible for the resource", func() {
+ request.Name = "self-hosted-shoot-" + shootName
+ request.Namespace = shootNamespace
+
+ Expect(handler.Handle(ctx, request)).To(Equal(responseAllowed))
+ })
+ })
+ })
+
+ Context("when requested for Leases", func() {
+ var name string
+
+ BeforeEach(func() {
+ name = "self-hosted-shoot-foo"
+
+ request.Name = name
+ request.UserInfo = gardenletUser
+ request.Resource = metav1.GroupVersionResource{
+ Group: coordinationv1.SchemeGroupVersion.Group,
+ Version: coordinationv1.SchemeGroupVersion.Version,
+ Resource: "leases",
+ }
+ })
+
+ DescribeTable("should not allow the request because no allowed verb",
+ func(operation admissionv1.Operation) {
+ request.Operation = operation
+
+ Expect(handler.Handle(ctx, request)).To(Equal(admission.Response{
+ AdmissionResponse: admissionv1.AdmissionResponse{
+ Allowed: false,
+ Result: &metav1.Status{
+ Code: int32(http.StatusBadRequest),
+ Message: fmt.Sprintf("unexpected operation: %q", operation),
+ },
+ },
+ }))
+ },
+
+ Entry("update", admissionv1.Update),
+ Entry("delete", admissionv1.Delete),
+ )
+
+ Context("when operation is create", func() {
+ BeforeEach(func() {
+ request.Operation = admissionv1.Create
+ })
+
+ It("should return an error because resource name is not prefixed", func() {
+ request.Name = "foo"
+
+ Expect(handler.Handle(ctx, request)).To(Equal(admission.Response{
+ AdmissionResponse: admissionv1.AdmissionResponse{
+ Allowed: false,
+ Result: &metav1.Status{
+ Code: int32(http.StatusBadRequest),
+ Message: `the resource for self-hosted shoots must be prefixed with "self-hosted-shoot-"`,
+ },
+ },
+ }))
+ })
+
+ It("should return an error because the requestor is not responsible for the resource", func() {
+ Expect(handler.Handle(ctx, request)).To(Equal(admission.Response{
+ AdmissionResponse: admissionv1.AdmissionResponse{
+ Allowed: false,
+ Result: &metav1.Status{
+ Code: int32(http.StatusForbidden),
+ Message: "object does not belong to shoot " + shootNamespace + "/" + shootName,
+ },
+ },
+ }))
+ })
+
+ It("should return success because the requestor is responsible for the resource", func() {
+ request.Name = "self-hosted-shoot-" + shootName
+ request.Namespace = shootNamespace
+
+ Expect(handler.Handle(ctx, request)).To(Equal(responseAllowed))
+ })
+ })
+ })
})
Context("gardenadm client", func() {
diff --git a/pkg/admissioncontroller/webhook/auth/seed/authorizer.go b/pkg/admissioncontroller/webhook/auth/seed/authorizer.go
index 1dce6811831..fbcc5e57f14 100644
--- a/pkg/admissioncontroller/webhook/auth/seed/authorizer.go
+++ b/pkg/admissioncontroller/webhook/auth/seed/authorizer.go
@@ -295,8 +295,13 @@ func (a *authorizer) authorizeLease(requestAuthorizer *authwebhook.RequestAuthor
}
// This is needed if the seed cluster is a garden cluster at the same time.
- if attrs.GetName() == "gardenlet-leader-election" &&
- slices.Contains([]string{"create", "get", "list", "watch", "update"}, attrs.GetVerb()) {
+ // TODO(rfranzke): Remove this logic once we only support gardener-operator-based Gardener deployments (in this
+ // case, the seed authorizer would not handle gardenlet's leader-election Lease requests since they are not
+ // performed in the virtual/garden cluster but in the runtime cluster).
+ if attrs.GetName() == "gardenlet-leader-election" {
+ if ok, reason := authwebhook.CheckVerb(requestAuthorizer.Log, attrs, "create", "get", "list", "update", "watch"); !ok {
+ return auth.DecisionNoOpinion, reason, nil
+ }
return auth.DecisionAllow, "", nil
}
diff --git a/pkg/admissioncontroller/webhook/auth/seed/authorizer_test.go b/pkg/admissioncontroller/webhook/auth/seed/authorizer_test.go
index bb798068779..bf84bf290c8 100644
--- a/pkg/admissioncontroller/webhook/auth/seed/authorizer_test.go
+++ b/pkg/admissioncontroller/webhook/auth/seed/authorizer_test.go
@@ -2406,6 +2406,44 @@ var _ = Describe("Seed", func() {
}
})
+ When("resource is gardenlet's leader election lease", func() {
+ BeforeEach(func() {
+ attrs.Name = "gardenlet-leader-election"
+ })
+
+ DescribeTable("should allow without consulting the graph for allowed verbs",
+ func(verb string) {
+ attrs.Verb = verb
+
+ decision, reason, err := authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionAllow))
+ Expect(reason).To(BeEmpty())
+ },
+
+ Entry("create", "create"),
+ Entry("get", "get"),
+ Entry("list", "list"),
+ Entry("watch", "watch"),
+ Entry("update", "update"),
+ )
+
+ DescribeTable("should deny without consulting the graph for disallowed verbs",
+ func(verb string) {
+ attrs.Verb = verb
+
+ decision, reason, err := authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionNoOpinion))
+ Expect(reason).To(ContainSubstring("only the following verbs are allowed for this resource type: [create get list update watch]"))
+ },
+
+ Entry("patch", "patch"),
+ Entry("delete", "delete"),
+ Entry("deletecollection", "deletecollection"),
+ )
+ })
+
DescribeTable("should allow without consulting the graph because verb is create",
func(verb string) {
attrs.Verb = verb
diff --git a/pkg/admissioncontroller/webhook/auth/shoot/authorizer.go b/pkg/admissioncontroller/webhook/auth/shoot/authorizer.go
index feb9b1eddc7..d6348896ae0 100644
--- a/pkg/admissioncontroller/webhook/auth/shoot/authorizer.go
+++ b/pkg/admissioncontroller/webhook/auth/shoot/authorizer.go
@@ -12,6 +12,7 @@ import (
"github.com/go-logr/logr"
certificatesv1 "k8s.io/api/certificates/v1"
+ coordinationv1 "k8s.io/api/coordination/v1"
corev1 "k8s.io/api/core/v1"
eventsv1 "k8s.io/api/events/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -62,6 +63,7 @@ var (
eventCoreResource = corev1.Resource("events")
eventResource = eventsv1.Resource("events")
gardenletResource = seedmanagementv1alpha1.Resource("gardenlets")
+ leaseResource = coordinationv1.Resource("leases")
projectResource = gardencorev1beta1.Resource("projects")
secretResource = corev1.Resource("secrets")
secretBindingResource = gardencorev1beta1.Resource("secretbindings")
@@ -119,6 +121,12 @@ func (a *authorizer) Authorize(ctx context.Context, attrs auth.Attributes) (auth
authwebhook.WithFieldSelectors(map[string]string{metav1.ObjectNameField: gardenletutils.ResourcePrefixSelfHostedShoot + requestAuthorizer.ToName}),
)
+ case leaseResource:
+ return requestAuthorizer.Check(graph.VertexTypeLease, attrs,
+ authwebhook.WithAllowedVerbs("get", "update", "patch", "list", "watch"),
+ authwebhook.WithAlwaysAllowedVerbs("create"),
+ )
+
case secretResource:
return a.authorizeSecret(ctx, requestAuthorizer, attrs)
@@ -131,7 +139,8 @@ func (a *authorizer) Authorize(ctx context.Context, attrs auth.Attributes) (auth
}
return requestAuthorizer.Check(graph.VertexTypeShoot, attrs,
- authwebhook.WithAllowedVerbs("get", "list", "watch"),
+ authwebhook.WithAllowedVerbs("update", "patch"),
+ authwebhook.WithAllowedSubresources("status"),
)
default:
diff --git a/pkg/admissioncontroller/webhook/auth/shoot/authorizer_test.go b/pkg/admissioncontroller/webhook/auth/shoot/authorizer_test.go
index 8e912903d01..baad1267cca 100644
--- a/pkg/admissioncontroller/webhook/auth/shoot/authorizer_test.go
+++ b/pkg/admissioncontroller/webhook/auth/shoot/authorizer_test.go
@@ -13,6 +13,7 @@ import (
. "github.com/onsi/gomega"
"go.uber.org/mock/gomock"
certificatesv1 "k8s.io/api/certificates/v1"
+ coordinationv1 "k8s.io/api/coordination/v1"
corev1 "k8s.io/api/core/v1"
eventsv1 "k8s.io/api/events/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -533,6 +534,86 @@ var _ = Describe("Shoot", func() {
)
})
+ Context("when requested for Leases", func() {
+ var (
+ name, namespace string
+ attrs *auth.AttributesRecord
+ )
+
+ BeforeEach(func() {
+ name, namespace = "foo", "bar"
+ attrs = &auth.AttributesRecord{
+ User: gardenletUser,
+ Name: name,
+ Namespace: namespace,
+ APIGroup: coordinationv1.SchemeGroupVersion.Group,
+ Resource: "leases",
+ ResourceRequest: true,
+ Verb: "get",
+ }
+ })
+
+ DescribeTable("should allow without consulting the graph because verb is create",
+ func(verb string) {
+ attrs.Verb = verb
+
+ decision, reason, err := authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionAllow))
+ Expect(reason).To(BeEmpty())
+ },
+
+ Entry("create", "create"),
+ )
+
+ DescribeTable("should return correct result if path exists",
+ func(verb string) {
+ attrs.Verb = verb
+
+ graph.EXPECT().HasPathFrom(graphutils.VertexTypeLease, namespace, name, graphutils.VertexTypeShoot, shootNamespace, shootName).Return(true)
+ decision, reason, err := authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionAllow))
+ Expect(reason).To(BeEmpty())
+
+ graph.EXPECT().HasPathFrom(graphutils.VertexTypeLease, namespace, name, graphutils.VertexTypeShoot, shootNamespace, shootName).Return(false)
+ decision, reason, err = authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionNoOpinion))
+ Expect(reason).To(ContainSubstring("no relationship found"))
+ },
+
+ Entry("get", "get"),
+ Entry("list", "list"),
+ Entry("watch", "watch"),
+ Entry("update", "update"),
+ Entry("patch", "patch"),
+ )
+
+ DescribeTable("should have no opinion because verb is not allowed",
+ func(verb string) {
+ attrs.Verb = verb
+
+ decision, reason, err := authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionNoOpinion))
+ Expect(reason).To(ContainSubstring("only the following verbs are allowed for this resource type: [create get list patch update watch]"))
+
+ },
+ Entry("delete", "delete"),
+ Entry("deletecollection", "deletecollection"),
+ )
+
+ It("should have no opinion because no allowed subresource", func() {
+ attrs.Subresource = "foo"
+
+ decision, reason, err := authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionNoOpinion))
+ Expect(reason).To(ContainSubstring("only the following subresources are allowed for this resource type: []"))
+ })
+ })
+
Context("when requested for Secrets", func() {
var (
name, namespace string
@@ -666,16 +747,48 @@ var _ = Describe("Shoot", func() {
decision, reason, err := authorizer.Authorize(ctx, attrs)
Expect(err).NotTo(HaveOccurred())
Expect(decision).To(Equal(auth.DecisionNoOpinion))
- Expect(reason).To(ContainSubstring("only the following verbs are allowed for this resource type: [get list watch]"))
+ Expect(reason).To(ContainSubstring("only the following verbs are allowed for this resource type: [patch update]"))
},
Entry("create", "create"),
- Entry("update", "update"),
- Entry("patch", "patch"),
Entry("delete", "delete"),
Entry("deletecollection", "deletecollection"),
)
+
+ It("should have no opinion because no allowed subresource", func() {
+ attrs.Subresource = "foo"
+ attrs.Verb = "patch"
+
+ decision, reason, err := authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionNoOpinion))
+ Expect(reason).To(ContainSubstring("only the following subresources are allowed for this resource type: [status]"))
+ })
+
+ DescribeTable("should return correct result if path exists",
+ func(verb, subresource string) {
+ attrs.Verb = verb
+ attrs.Subresource = subresource
+
+ graph.EXPECT().HasPathFrom(graphutils.VertexTypeShoot, namespace, name, graphutils.VertexTypeShoot, shootNamespace, shootName).Return(true)
+ decision, reason, err := authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionAllow))
+ Expect(reason).To(BeEmpty())
+
+ graph.EXPECT().HasPathFrom(graphutils.VertexTypeShoot, namespace, name, graphutils.VertexTypeShoot, shootNamespace, shootName).Return(false)
+ decision, reason, err = authorizer.Authorize(ctx, attrs)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(decision).To(Equal(auth.DecisionNoOpinion))
+ Expect(reason).To(ContainSubstring("no relationship found"))
+ },
+
+ Entry("patch w/o subresource", "patch", ""),
+ Entry("patch w/ status subresource", "patch", "status"),
+ Entry("update w/o subresource", "update", ""),
+ Entry("update w/ status subresource", "update", "status"),
+ )
})
})
diff --git a/pkg/apis/core/v1beta1/constants/types_constants.go b/pkg/apis/core/v1beta1/constants/types_constants.go
index 3991c6e49e0..f5af73e1e92 100644
--- a/pkg/apis/core/v1beta1/constants/types_constants.go
+++ b/pkg/apis/core/v1beta1/constants/types_constants.go
@@ -322,6 +322,8 @@ const (
// ShootDisableIstioTLSTermination is a constant for an annotation on a Shoot stating that the Istio TLS termination
// for its kube-apiserver shall be disabled.
ShootDisableIstioTLSTermination = "shoot.gardener.cloud/disable-istio-tls-termination"
+ // ShootIsSelfHosted is a constant for a label on a Shoot indicating that it is self-hosted.
+ ShootIsSelfHosted = "shoot.gardener.cloud/self-hosted"
// ShootAlphaControlPlaneScaleDownDisabled is a constant for an annotation on the Shoot resource stating that the
// automatic scale-down shall be disabled for the etcd, kube-apiserver, kube-controller-manager.
diff --git a/pkg/apis/core/v1beta1/types_seed.go b/pkg/apis/core/v1beta1/types_seed.go
index 647b8964d9f..8768f9d3605 100644
--- a/pkg/apis/core/v1beta1/types_seed.go
+++ b/pkg/apis/core/v1beta1/types_seed.go
@@ -490,8 +490,6 @@ const (
SeedBackupBucketsReady ConditionType = "BackupBucketsReady"
// SeedExtensionsReady is a constant for a condition type indicating that the extensions are ready.
SeedExtensionsReady ConditionType = "ExtensionsReady"
- // SeedGardenletReady is a constant for a condition type indicating that the Gardenlet is ready.
- SeedGardenletReady ConditionType = "GardenletReady"
// SeedSystemComponentsHealthy is a constant for a condition type indicating the system components health.
SeedSystemComponentsHealthy ConditionType = "SeedSystemComponentsHealthy"
// SeedEmergencyStopShootReconciliations is a constant for a condition type indicating disabled shoot reconciliations.
diff --git a/pkg/apis/core/v1beta1/types_utils.go b/pkg/apis/core/v1beta1/types_utils.go
index 99f43a58658..e3ceb9a18e6 100644
--- a/pkg/apis/core/v1beta1/types_utils.go
+++ b/pkg/apis/core/v1beta1/types_utils.go
@@ -62,4 +62,7 @@ const (
// ManagedResourceProgressingRolloutStuck is a constant for a reason in a condition that indicates
// managed resource progressing condition is stuck in the true state for more than the threshold time.
ManagedResourceProgressingRolloutStuck = "ProgressingRolloutStuck"
+
+ // GardenletReady is a constant for a condition type indicating that the Gardenlet is ready.
+ GardenletReady ConditionType = "GardenletReady"
)
diff --git a/pkg/apiserver/registry/core/shoot/strategy.go b/pkg/apiserver/registry/core/shoot/strategy.go
index 9abdddfce49..a2e1a0ea42f 100644
--- a/pkg/apiserver/registry/core/shoot/strategy.go
+++ b/pkg/apiserver/registry/core/shoot/strategy.go
@@ -11,6 +11,7 @@ import (
"time"
apiequality "k8s.io/apimachinery/pkg/api/equality"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
@@ -190,6 +191,15 @@ func (shootStrategy) Canonicalize(obj runtime.Object) {
shoot.Spec.Kubernetes.ClusterAutoscaler.MaxEmptyBulkDelete = nil
}
gardenerutils.MaintainSeedNameLabels(shoot, shoot.Spec.SeedName, shoot.Status.SeedName)
+ maintainIsSelfHostedLabel(shoot)
+}
+
+func maintainIsSelfHostedLabel(shoot *core.Shoot) {
+ if gardencorehelper.IsShootSelfHosted(shoot.Spec.Provider.Workers) {
+ metav1.SetMetaDataLabel(&shoot.ObjectMeta, v1beta1constants.ShootIsSelfHosted, "true")
+ } else {
+ delete(shoot.Labels, v1beta1constants.ShootIsSelfHosted)
+ }
}
func (shootStrategy) AllowCreateOnUpdate() bool {
diff --git a/pkg/apiserver/registry/core/shoot/strategy_test.go b/pkg/apiserver/registry/core/shoot/strategy_test.go
index 03bad3a609b..2593781f88a 100644
--- a/pkg/apiserver/registry/core/shoot/strategy_test.go
+++ b/pkg/apiserver/registry/core/shoot/strategy_test.go
@@ -667,6 +667,26 @@ var _ = Describe("Strategy", func() {
Expect(shoot.Spec.Kubernetes.ClusterAutoscaler.MaxEmptyBulkDelete).To(BeNil())
})
})
+
+ Context("self-hosted shoots", func() {
+ It("should correctly add the self-hosted label", func() {
+ shoot.Spec.Provider.Workers = append(shoot.Spec.Provider.Workers, core.Worker{ControlPlane: &core.WorkerControlPlane{}})
+
+ strategy.Canonicalize(shoot)
+
+ Expect(shoot.Labels).To(Equal(map[string]string{
+ "shoot.gardener.cloud/self-hosted": "true",
+ }))
+ })
+
+ It("should correctly remove the self-hosted label", func() {
+ metav1.SetMetaDataLabel(&shoot.ObjectMeta, "shoot.gardener.cloud/self-hosted", "true")
+
+ strategy.Canonicalize(shoot)
+
+ Expect(shoot.Labels).To(BeEmpty())
+ })
+ })
})
Context("BindingStrategy", func() {
diff --git a/pkg/component/garden/backupentry/backupentry.go b/pkg/component/garden/backupentry/backupentry.go
index 24cbd393cc7..4cd8600e649 100644
--- a/pkg/component/garden/backupentry/backupentry.go
+++ b/pkg/component/garden/backupentry/backupentry.go
@@ -52,7 +52,7 @@ type Values struct {
}
// New creates a new instance of DeployWaiter for a BackupEntry. It takes a garden client and returns a deployer for a
-// // core.gardener.cloud/v1beta1.BackupEntry resource in the garden cluster.
+// core.gardener.cloud/v1beta1.BackupEntry resource in the garden cluster.
func New(
log logr.Logger,
client client.Client,
diff --git a/pkg/controllermanager/controller/add.go b/pkg/controllermanager/controller/add.go
index 70b862b4158..d4fad5a7fd9 100644
--- a/pkg/controllermanager/controller/add.go
+++ b/pkg/controllermanager/controller/add.go
@@ -11,6 +11,7 @@ import (
kubernetesclientset "k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/manager"
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/controllermanager/controller/bastion"
"github.com/gardener/gardener/pkg/controllermanager/controller/certificatesigningrequest"
@@ -20,6 +21,7 @@ import (
"github.com/gardener/gardener/pkg/controllermanager/controller/credentialsbinding"
"github.com/gardener/gardener/pkg/controllermanager/controller/event"
"github.com/gardener/gardener/pkg/controllermanager/controller/exposureclass"
+ "github.com/gardener/gardener/pkg/controllermanager/controller/gardenletlifecycle"
"github.com/gardener/gardener/pkg/controllermanager/controller/managedseedset"
"github.com/gardener/gardener/pkg/controllermanager/controller/namespacedcloudprofile"
"github.com/gardener/gardener/pkg/controllermanager/controller/project"
@@ -92,6 +94,13 @@ func AddToManager(ctx context.Context, mgr manager.Manager, cfg *controllermanag
return fmt.Errorf("failed adding ExposureClass controller: %w", err)
}
+ if err := (&gardenletlifecycle.Reconciler{
+ Config: *cfg.Controllers.Seed,
+ LeaseNamespace: gardencorev1beta1.GardenerSeedLeaseNamespace,
+ }).AddToManager(mgr); err != nil {
+ return fmt.Errorf("failed adding gardenlet lifecycle reconciler: %w", err)
+ }
+
if err := (&managedseedset.Reconciler{
Config: *cfg.Controllers.ManagedSeedSet,
}).AddToManager(ctx, mgr); err != nil {
diff --git a/pkg/controllermanager/controller/exposureclass/exposureclass_suite_test.go b/pkg/controllermanager/controller/exposureclass/exposureclass_suite_test.go
index 575a972e5d6..9ebaf9bbb94 100644
--- a/pkg/controllermanager/controller/exposureclass/exposureclass_suite_test.go
+++ b/pkg/controllermanager/controller/exposureclass/exposureclass_suite_test.go
@@ -11,7 +11,7 @@ import (
. "github.com/onsi/gomega"
)
-func TestControllerRegistration(t *testing.T) {
+func TestExposureClass(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "ControllerManager Controller ExposureClass Suite")
}
diff --git a/pkg/controllermanager/controller/gardenletlifecycle/add.go b/pkg/controllermanager/controller/gardenletlifecycle/add.go
new file mode 100644
index 00000000000..dc24cd6bd6d
--- /dev/null
+++ b/pkg/controllermanager/controller/gardenletlifecycle/add.go
@@ -0,0 +1,79 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package gardenletlifecycle
+
+import (
+ "context"
+ "fmt"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/types"
+ "k8s.io/client-go/util/workqueue"
+ "k8s.io/utils/clock"
+ "k8s.io/utils/ptr"
+ "sigs.k8s.io/controller-runtime/pkg/builder"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/controller"
+ "sigs.k8s.io/controller-runtime/pkg/event"
+ "sigs.k8s.io/controller-runtime/pkg/handler"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+ "sigs.k8s.io/controller-runtime/pkg/predicate"
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
+
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
+ predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
+)
+
+// ControllerName is the name of this controller.
+const ControllerName = "gardenlet-lifecycle"
+
+// Request contains the namespace/name of the object as well as information whether it is a self-hosted Shoot.
+type Request struct {
+ reconcile.Request
+
+ IsSelfHostedShoot bool
+}
+
+// AddToManager adds Reconciler to the given manager.
+func (r *Reconciler) AddToManager(mgr manager.Manager) error {
+ if r.Client == nil {
+ r.Client = mgr.GetClient()
+ }
+ if r.Clock == nil {
+ r.Clock = clock.RealClock{}
+ }
+
+ shootIsSelfHostedPredicate, err := predicate.LabelSelectorPredicate(metav1.LabelSelector{MatchLabels: map[string]string{v1beta1constants.ShootIsSelfHosted: "true"}})
+ if err != nil {
+ return fmt.Errorf("failed computing shoot-is-self-hosted predicate: %w", err)
+ }
+
+ return builder.
+ TypedControllerManagedBy[Request](mgr).
+ Named(ControllerName).
+ Watches(&gardencorev1beta1.Seed{}, r.EventHandler(), builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create))).
+ Watches(&gardencorev1beta1.Shoot{}, r.EventHandler(), builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create), shootIsSelfHostedPredicate)).
+ WithOptions(controller.TypedOptions[Request]{
+ MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
+ ReconciliationTimeout: r.Config.SyncPeriod.Duration,
+ }).
+ Complete(r)
+}
+
+// EventHandler returns a handler for events.
+func (r *Reconciler) EventHandler() handler.TypedEventHandler[client.Object, Request] {
+ return &handler.TypedFuncs[client.Object, Request]{
+ CreateFunc: func(_ context.Context, e event.TypedCreateEvent[client.Object], q workqueue.TypedRateLimitingInterface[Request]) {
+ if e.Object != nil {
+ _, isSelfHostedShoot := e.Object.(*gardencorev1beta1.Shoot)
+ q.Add(Request{
+ Request: reconcile.Request{NamespacedName: types.NamespacedName{Name: e.Object.GetName(), Namespace: e.Object.GetNamespace()}},
+ IsSelfHostedShoot: isSelfHostedShoot,
+ })
+ }
+ },
+ }
+}
diff --git a/pkg/controllermanager/controller/gardenletlifecycle/add_test.go b/pkg/controllermanager/controller/gardenletlifecycle/add_test.go
new file mode 100644
index 00000000000..947740c2c8e
--- /dev/null
+++ b/pkg/controllermanager/controller/gardenletlifecycle/add_test.go
@@ -0,0 +1,77 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package gardenletlifecycle_test
+
+import (
+ "context"
+
+ . "github.com/onsi/ginkgo/v2"
+ "go.uber.org/mock/gomock"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/types"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/event"
+ "sigs.k8s.io/controller-runtime/pkg/handler"
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
+
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ . "github.com/gardener/gardener/pkg/controllermanager/controller/gardenletlifecycle"
+ mockworkqueue "github.com/gardener/gardener/third_party/mock/client-go/util/workqueue"
+)
+
+var _ = Describe("Add", func() {
+ var reconciler *Reconciler
+
+ BeforeEach(func() {
+ reconciler = &Reconciler{}
+ })
+
+ Describe("#EventHandler", func() {
+ var (
+ ctx = context.Background()
+ hdlr handler.TypedEventHandler[client.Object, Request]
+ queue *mockworkqueue.MockTypedRateLimitingInterface[Request]
+ )
+
+ BeforeEach(func() {
+ hdlr = reconciler.EventHandler()
+ queue = mockworkqueue.NewMockTypedRateLimitingInterface[Request](gomock.NewController(GinkgoT()))
+ })
+
+ It("should correctly enqueue Seeds", func() {
+ obj := &gardencorev1beta1.Seed{ObjectMeta: metav1.ObjectMeta{Name: "seed"}}
+
+ queue.EXPECT().Add(Request{
+ Request: reconcile.Request{NamespacedName: types.NamespacedName{Name: "seed"}},
+ IsSelfHostedShoot: false,
+ })
+
+ hdlr.Create(ctx, event.CreateEvent{Object: obj}, queue)
+ })
+
+ It("should correctly enqueue Shoots", func() {
+ obj := &gardencorev1beta1.Shoot{ObjectMeta: metav1.ObjectMeta{Name: "shoot", Namespace: "shoot-namespace"}}
+
+ queue.EXPECT().Add(Request{
+ Request: reconcile.Request{NamespacedName: types.NamespacedName{Name: "shoot", Namespace: "shoot-namespace"}},
+ IsSelfHostedShoot: true,
+ })
+
+ hdlr.Create(ctx, event.CreateEvent{Object: obj}, queue)
+ })
+
+ It("should not enqueue the object for Update events", func() {
+ hdlr.Update(ctx, event.UpdateEvent{}, queue)
+ })
+
+ It("should not enqueue the object for Delete events", func() {
+ hdlr.Delete(ctx, event.DeleteEvent{}, queue)
+ })
+
+ It("should not enqueue the object for Generic events", func() {
+ hdlr.Generic(ctx, event.GenericEvent{}, queue)
+ })
+ })
+})
diff --git a/pkg/controllermanager/controller/gardenletlifecycle/gardenletlifecycle_suite_test.go b/pkg/controllermanager/controller/gardenletlifecycle/gardenletlifecycle_suite_test.go
new file mode 100644
index 00000000000..6a9d82905ae
--- /dev/null
+++ b/pkg/controllermanager/controller/gardenletlifecycle/gardenletlifecycle_suite_test.go
@@ -0,0 +1,17 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package gardenletlifecycle_test
+
+import (
+ "testing"
+
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+)
+
+func TestGardenletLifecycle(t *testing.T) {
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "ControllerManager Controller GardenletLifecycle Suite")
+}
diff --git a/pkg/controllermanager/controller/seed/lifecycle/reconciler.go b/pkg/controllermanager/controller/gardenletlifecycle/reconciler.go
similarity index 54%
rename from pkg/controllermanager/controller/seed/lifecycle/reconciler.go
rename to pkg/controllermanager/controller/gardenletlifecycle/reconciler.go
index 6e0778f5ed9..4475f53e581 100644
--- a/pkg/controllermanager/controller/seed/lifecycle/reconciler.go
+++ b/pkg/controllermanager/controller/gardenletlifecycle/reconciler.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
-package lifecycle
+package gardenletlifecycle
import (
"context"
@@ -23,12 +23,14 @@ import (
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/utils/flow"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
+ "github.com/gardener/gardener/pkg/utils/gardener/gardenlet"
kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes"
)
-// Reconciler reconciles Seeds and checks whether the responsible gardenlet is regularly sending heartbeats. If not, it
-// sets the GardenletReady condition of the Seed to Unknown after some grace period passed. If the gardenlet still did
-// not send heartbeats and another grace period passed then also all shoot conditions and constraints are set to Unknown.
+// Reconciler reconciles Seeds or self-hosted Shoots and checks whether the responsible gardenlet is regularly sending
+// heartbeats. If not, it sets the GardenletReady condition to Unknown after some grace period passed. If the gardenlet
+// still did not send heartbeats and another grace period passed then also all (other) Shoot conditions and constraints
+// are set to Unknown.
type Reconciler struct {
Client client.Client
Config controllermanagerconfigv1alpha1.SeedControllerConfiguration
@@ -36,28 +38,30 @@ type Reconciler struct {
LeaseNamespace string
}
-// Reconcile reconciles Seeds and checks whether the responsible gardenlet is regularly sending heartbeats. If not, it
-// sets the GardenletReady condition of the Seed to Unknown after some grace period passed. If the gardenlet still did
-// not send heartbeats and another grace period passed then also all shoot conditions and constraints are set to Unknown.
-func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
+// Reconcile reconciles Seeds or self-hosted Shoots and checks whether the responsible gardenlet is regularly sending
+// heartbeats. If not, it sets the GardenletReady condition to Unknown after some grace period passed. If the gardenlet
+// still did not send heartbeats and another grace period passed then also all (other) Shoot conditions and constraints
+// are set to Unknown.
+func (r *Reconciler) Reconcile(ctx context.Context, req Request) (reconcile.Result, error) {
log := logf.FromContext(ctx)
- seed := &gardencorev1beta1.Seed{}
- if err := r.Client.Get(ctx, req.NamespacedName, seed); err != nil {
+ obj := newObj(req)
+ if err := r.Client.Get(ctx, client.ObjectKeyFromObject(obj), obj); err != nil {
if apierrors.IsNotFound(err) {
log.V(1).Info("Object is gone, stop reconciling")
return reconcile.Result{}, nil
}
return reconcile.Result{}, fmt.Errorf("error retrieving object from store: %w", err)
}
+ log = log.WithValues("object", client.ObjectKeyFromObject(obj), "isSelfHostedShoot", req.IsSelfHostedShoot)
- // New seeds don't have conditions - gardenlet never reported anything yet. Wait for grace period.
- if len(seed.Status.Conditions) == 0 {
+ // New objects don't have conditions - gardenlet never reported anything yet. Wait for grace period.
+ if len(conditions(obj)) == 0 {
return reconcile.Result{RequeueAfter: r.Config.SyncPeriod.Duration}, nil
}
lease := &coordinationv1.Lease{}
- if err := r.Client.Get(ctx, client.ObjectKey{Namespace: r.LeaseNamespace, Name: seed.Name}, lease); client.IgnoreNotFound(err) != nil {
+ if err := r.Client.Get(ctx, r.leaseKey(req), lease); client.IgnoreNotFound(err) != nil {
return reconcile.Result{}, err
}
@@ -69,28 +73,28 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
log.Info("Lease was not renewed in time",
"renewTime", lease.Spec.RenewTime.UTC(),
"now", r.Clock.Now().UTC(),
- "seedMonitorPeriod", r.Config.MonitorPeriod.Duration,
+ "monitorPeriod", r.Config.MonitorPeriod.Duration,
)
}
- log.Info("Setting Seed status to 'Unknown' as gardenlet stopped reporting seed status")
+ log.Info("Setting GardenletReady condition status to 'Unknown' as gardenlet stopped updating its Lease")
- bldr, err := v1beta1helper.NewConditionBuilder(gardencorev1beta1.SeedGardenletReady)
+ bldr, err := v1beta1helper.NewConditionBuilder(gardencorev1beta1.GardenletReady)
if err != nil {
return reconcile.Result{}, err
}
- conditionGardenletReady := v1beta1helper.GetCondition(seed.Status.Conditions, gardencorev1beta1.SeedGardenletReady)
+ conditionGardenletReady := v1beta1helper.GetCondition(conditions(obj), gardencorev1beta1.GardenletReady)
if conditionGardenletReady != nil {
bldr.WithOldCondition(*conditionGardenletReady)
}
bldr.WithStatus(gardencorev1beta1.ConditionUnknown)
- bldr.WithReason("SeedStatusUnknown")
- bldr.WithMessage("Gardenlet stopped posting seed status.")
+ bldr.WithReason("StatusUnknown")
+ bldr.WithMessage("Gardenlet stopped posting status updates.")
if newCondition, update := bldr.WithClock(r.Clock).Build(); update {
- seed.Status.Conditions = v1beta1helper.MergeConditions(seed.Status.Conditions, newCondition)
- if err := r.Client.Status().Update(ctx, seed); err != nil {
+ setConditions(obj, v1beta1helper.MergeConditions(conditions(obj), newCondition))
+ if err := r.Client.Status().Update(ctx, obj); err != nil {
return reconcile.Result{}, err
}
conditionGardenletReady = &newCondition
@@ -98,27 +102,29 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
// If the gardenlet's client certificate is expired and the seed belongs to a `ManagedSeed` then we reconcile it in
// order to re-bootstrap the gardenlet.
- if seed.Status.ClientCertificateExpirationTimestamp != nil && seed.Status.ClientCertificateExpirationTimestamp.UTC().Before(r.Clock.Now().UTC()) {
- managedSeed, err := kubernetesutils.GetManagedSeedByName(ctx, r.Client, seed.Name)
- if err != nil {
- return reconcile.Result{}, err
- }
+ if !req.IsSelfHostedShoot {
+ if seed := obj.(*gardencorev1beta1.Seed); seed.Status.ClientCertificateExpirationTimestamp != nil && seed.Status.ClientCertificateExpirationTimestamp.UTC().Before(r.Clock.Now().UTC()) {
+ managedSeed, err := kubernetesutils.GetManagedSeedByName(ctx, r.Client, seed.Name)
+ if err != nil {
+ return reconcile.Result{}, err
+ }
- if managedSeed != nil {
- log.Info("Triggering ManagedSeed reconciliation since gardenlet client certificate is expired", "managedSeed", client.ObjectKeyFromObject(managedSeed))
+ if managedSeed != nil {
+ log.Info("Triggering ManagedSeed reconciliation since gardenlet client certificate is expired", "managedSeed", client.ObjectKeyFromObject(managedSeed))
- patch := client.MergeFrom(managedSeed.DeepCopy())
- metav1.SetMetaDataAnnotation(&managedSeed.ObjectMeta, v1beta1constants.GardenerOperation, v1beta1constants.GardenerOperationReconcile)
- if err := r.Client.Patch(ctx, managedSeed, patch); err != nil {
- return reconcile.Result{}, err
+ patch := client.MergeFrom(managedSeed.DeepCopy())
+ metav1.SetMetaDataAnnotation(&managedSeed.ObjectMeta, v1beta1constants.GardenerOperation, v1beta1constants.GardenerOperationReconcile)
+ if err := r.Client.Patch(ctx, managedSeed, patch); err != nil {
+ return reconcile.Result{}, err
+ }
}
}
}
- // If the `GardenletReady` condition is `Unknown` for at least the configured `shootMonitorPeriod` then we will mark the conditions
- // and constraints for all the shoots that belong to this seed as `Unknown`. The reason is that the gardenlet didn't send a heartbeat
- // anymore, hence, it most likely didn't check the shoot status. This means that the current shoot status might not reflect the truth
- // anymore. We are indicating this by marking it as `Unknown`.
+ // If the `GardenletReady` condition is `Unknown` for at least the configured `shootMonitorPeriod` then we will mark
+ // the conditions and constraints for affected Shoots as `Unknown`. The reason is that the gardenlet didn't send a
+ // heartbeat anymore, hence, it most likely didn't check the shoot status. This means that the current shoot status
+ // might not reflect the truth anymore. We are indicating this by marking it as `Unknown`.
if conditionGardenletReady != nil && conditionGardenletReady.LastTransitionTime.UTC().Add(r.Config.ShootMonitorPeriod.Duration).After(r.Clock.Now().UTC()) {
return reconcile.Result{RequeueAfter: r.Config.SyncPeriod.Duration}, nil
}
@@ -128,21 +134,24 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
gardenletOfflineSince = conditionGardenletReady.LastTransitionTime.UTC()
}
- log.Info("Gardenlet has not sent heartbeats for at least the configured shoot monitor period, setting shoot conditions and constraints to 'Unknown' for all shoots on this seed",
+ log.Info("Gardenlet has not sent heartbeats for at least the configured shoot monitor period, setting shoot conditions and constraints to 'Unknown' for all affected Shoots",
"gardenletOfflineSince", gardenletOfflineSince,
"now", r.Clock.Now().UTC(),
"shootMonitorPeriod", r.Config.ShootMonitorPeriod.Duration,
)
shootList := &gardencorev1beta1.ShootList{}
- if err := r.Client.List(ctx, shootList, client.MatchingFields{core.ShootStatusSeedName: seed.Name}); err != nil {
- return reconcile.Result{}, err
+ if req.IsSelfHostedShoot {
+ shootList.Items = append(shootList.Items, *obj.(*gardencorev1beta1.Shoot))
+ } else {
+ if err := r.Client.List(ctx, shootList, client.MatchingFields{core.ShootStatusSeedName: req.Name}); err != nil {
+ return reconcile.Result{}, err
+ }
}
var fns []flow.TaskFn
- for _, s := range shootList.Items {
- shoot := s
+ for _, shoot := range shootList.Items {
fns = append(fns, func(ctx context.Context) error {
return setShootStatusToUnknown(ctx, r.Clock, r.Client, &shoot)
})
@@ -194,3 +203,39 @@ func conditionMapToConditions(m map[gardencorev1beta1.ConditionType]gardencorev1
return output
}
+
+func newObj(req Request) client.Object {
+ if req.IsSelfHostedShoot {
+ return &gardencorev1beta1.Shoot{ObjectMeta: metav1.ObjectMeta{Name: req.Name, Namespace: req.Namespace}}
+ }
+ return &gardencorev1beta1.Seed{ObjectMeta: metav1.ObjectMeta{Name: req.Name}}
+}
+
+func conditions(o client.Object) []gardencorev1beta1.Condition {
+ switch obj := o.(type) {
+ case *gardencorev1beta1.Seed:
+ return obj.Status.Conditions
+ case *gardencorev1beta1.Shoot:
+ return obj.Status.Conditions
+ default:
+ panic("unexpected object")
+ }
+}
+
+func setConditions(o client.Object, conditions []gardencorev1beta1.Condition) {
+ switch obj := o.(type) {
+ case *gardencorev1beta1.Seed:
+ obj.Status.Conditions = conditions
+ case *gardencorev1beta1.Shoot:
+ obj.Status.Conditions = conditions
+ default:
+ panic("unexpected object")
+ }
+}
+
+func (r *Reconciler) leaseKey(req Request) client.ObjectKey {
+ if req.IsSelfHostedShoot {
+ return client.ObjectKey{Namespace: req.Namespace, Name: gardenlet.ResourcePrefixSelfHostedShoot + req.Name}
+ }
+ return client.ObjectKey{Namespace: r.LeaseNamespace, Name: req.Name}
+}
diff --git a/pkg/controllermanager/controller/managedseedset/add_test.go b/pkg/controllermanager/controller/managedseedset/add_test.go
index be4cba2aa3b..6668ea34190 100644
--- a/pkg/controllermanager/controller/managedseedset/add_test.go
+++ b/pkg/controllermanager/controller/managedseedset/add_test.go
@@ -470,7 +470,7 @@ var _ = Describe("Add", func() {
It("should return true for update and false for create and delete event when Seed Ready status changes", func() {
newSeed.Status.Conditions = []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedBackupBucketsReady, Status: gardencorev1beta1.ConditionTrue},
}
@@ -527,12 +527,12 @@ var _ = Describe("Add", func() {
It("should return true for create, update and delete event when pending replica has SeedNotReady status and Seed is ready", func() {
oldSeed.Status.Conditions = []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedBackupBucketsReady, Status: gardencorev1beta1.ConditionTrue},
}
newSeed.Status.Conditions = []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedBackupBucketsReady, Status: gardencorev1beta1.ConditionTrue},
}
diff --git a/pkg/controllermanager/controller/managedseedset/replica.go b/pkg/controllermanager/controller/managedseedset/replica.go
index 9942762b5ba..5166190e4dc 100644
--- a/pkg/controllermanager/controller/managedseedset/replica.go
+++ b/pkg/controllermanager/controller/managedseedset/replica.go
@@ -314,7 +314,7 @@ func managedSeedRegistered(managedSeed *seedmanagementv1alpha1.ManagedSeed) bool
}
func seedReady(seed *gardencorev1beta1.Seed) bool {
- conditionGardenletReady := v1beta1helper.GetCondition(seed.Status.Conditions, gardencorev1beta1.SeedGardenletReady)
+ conditionGardenletReady := v1beta1helper.GetCondition(seed.Status.Conditions, gardencorev1beta1.GardenletReady)
conditionBackupBucketsReady := v1beta1helper.GetCondition(seed.Status.Conditions, gardencorev1beta1.SeedBackupBucketsReady)
conditionSystemComponentsHealthy := v1beta1helper.GetCondition(seed.Status.Conditions, gardencorev1beta1.SeedSystemComponentsHealthy)
return seed.Generation == seed.Status.ObservedGeneration && seed.DeletionTimestamp == nil &&
diff --git a/pkg/controllermanager/controller/managedseedset/replica_test.go b/pkg/controllermanager/controller/managedseedset/replica_test.go
index 70e92d54369..e731154dbd9 100644
--- a/pkg/controllermanager/controller/managedseedset/replica_test.go
+++ b/pkg/controllermanager/controller/managedseedset/replica_test.go
@@ -160,7 +160,7 @@ var _ = Describe("Replica", func() {
var conditions []gardencorev1beta1.Condition
if gardenletReady {
conditions = append(conditions, gardencorev1beta1.Condition{
- Type: gardencorev1beta1.SeedGardenletReady,
+ Type: gardencorev1beta1.GardenletReady,
Status: gardencorev1beta1.ConditionTrue,
})
}
diff --git a/pkg/controllermanager/controller/seed/add.go b/pkg/controllermanager/controller/seed/add.go
index 003f64a64d0..3a8d99ff200 100644
--- a/pkg/controllermanager/controller/seed/add.go
+++ b/pkg/controllermanager/controller/seed/add.go
@@ -13,7 +13,6 @@ import (
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/controllermanager/controller/seed/backupbucketscheck"
"github.com/gardener/gardener/pkg/controllermanager/controller/seed/extensionscheck"
- "github.com/gardener/gardener/pkg/controllermanager/controller/seed/lifecycle"
"github.com/gardener/gardener/pkg/controllermanager/controller/seed/reference"
"github.com/gardener/gardener/pkg/controllermanager/controller/seed/secrets"
)
@@ -32,12 +31,6 @@ func AddToManager(mgr manager.Manager, cfg controllermanagerconfigv1alpha1.Contr
return fmt.Errorf("failed adding extensions check reconciler: %w", err)
}
- if err := (&lifecycle.Reconciler{
- Config: *cfg.Controllers.Seed,
- }).AddToManager(mgr); err != nil {
- return fmt.Errorf("failed adding lifecycle reconciler: %w", err)
- }
-
if err := (&secrets.Reconciler{}).AddToManager(mgr); err != nil {
return fmt.Errorf("failed adding secrets reconciler: %w", err)
}
diff --git a/pkg/controllermanager/controller/seed/lifecycle/add.go b/pkg/controllermanager/controller/seed/lifecycle/add.go
deleted file mode 100644
index 6e093a9067d..00000000000
--- a/pkg/controllermanager/controller/seed/lifecycle/add.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-package lifecycle
-
-import (
- "k8s.io/utils/clock"
- "k8s.io/utils/ptr"
- "sigs.k8s.io/controller-runtime/pkg/builder"
- "sigs.k8s.io/controller-runtime/pkg/controller"
- "sigs.k8s.io/controller-runtime/pkg/manager"
-
- gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
- predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
-)
-
-// ControllerName is the name of this controller.
-const ControllerName = "seed-lifecycle"
-
-// AddToManager adds Reconciler to the given manager.
-func (r *Reconciler) AddToManager(mgr manager.Manager) error {
- if r.Client == nil {
- r.Client = mgr.GetClient()
- }
- if r.Clock == nil {
- r.Clock = clock.RealClock{}
- }
- if r.LeaseNamespace == "" {
- r.LeaseNamespace = gardencorev1beta1.GardenerSeedLeaseNamespace
- }
-
- return builder.
- ControllerManagedBy(mgr).
- Named(ControllerName).
- For(&gardencorev1beta1.Seed{}, builder.WithPredicates(predicateutils.ForEventTypes(predicateutils.Create))).
- WithOptions(controller.Options{
- MaxConcurrentReconciles: ptr.Deref(r.Config.ConcurrentSyncs, 0),
- ReconciliationTimeout: r.Config.SyncPeriod.Duration,
- }).
- Complete(r)
-}
diff --git a/pkg/controllermanager/controller/shoot/conditions/add_test.go b/pkg/controllermanager/controller/shoot/conditions/add_test.go
index 5a8f094db76..978b24ce7a3 100644
--- a/pkg/controllermanager/controller/shoot/conditions/add_test.go
+++ b/pkg/controllermanager/controller/shoot/conditions/add_test.go
@@ -63,11 +63,11 @@ var _ = Describe("Add", func() {
oldSeed, newSeed *gardencorev1beta1.Seed
gardenletReady = []gardencorev1beta1.Condition{{
- Type: gardencorev1beta1.SeedGardenletReady,
+ Type: gardencorev1beta1.GardenletReady,
Status: gardencorev1beta1.ConditionTrue,
}}
gardenletNotReady = []gardencorev1beta1.Condition{{
- Type: gardencorev1beta1.SeedGardenletReady,
+ Type: gardencorev1beta1.GardenletReady,
Status: gardencorev1beta1.ConditionFalse,
}}
)
diff --git a/pkg/gardenlet/controller/add.go b/pkg/gardenlet/controller/add.go
index be3da54bb35..d26ce197f65 100644
--- a/pkg/gardenlet/controller/add.go
+++ b/pkg/gardenlet/controller/add.go
@@ -30,6 +30,7 @@ import (
"github.com/gardener/gardener/pkg/gardenlet/controller/networkpolicy"
"github.com/gardener/gardener/pkg/gardenlet/controller/seed"
"github.com/gardener/gardener/pkg/gardenlet/controller/shoot"
+ "github.com/gardener/gardener/pkg/gardenlet/controller/shoot/lease"
"github.com/gardener/gardener/pkg/gardenlet/controller/tokenrequestor/workloadidentity"
"github.com/gardener/gardener/pkg/gardenlet/controller/vpaevictionrequirements"
"github.com/gardener/gardener/pkg/healthz"
@@ -88,6 +89,11 @@ func AddToManager(
return fmt.Errorf("failed adding Gardenlet controller: %w", err)
}
+ // TODO(rfranzke): Remove this once all shoot reconcilers are added via `shoot.AddToManager`.
+ if err := lease.AddToManager(mgr, gardenCluster, seedClientSet.RESTClient(), healthManager, nil); err != nil {
+ return fmt.Errorf("failed adding shoot-lease reconciler: %w", err)
+ }
+
return nil
}
@@ -136,7 +142,7 @@ func AddToManager(
return fmt.Errorf("failed adding Seed controller: %w", err)
}
- if err := shoot.AddToManager(ctx, mgr, gardenCluster, seedCluster, seedClientSet, shootClientMap, *cfg, identity, gardenClusterIdentity); err != nil {
+ if err := shoot.AddToManager(ctx, mgr, gardenCluster, seedCluster, seedClientSet, shootClientMap, *cfg, identity, gardenClusterIdentity, healthManager); err != nil {
return fmt.Errorf("failed adding Shoot controller: %w", err)
}
diff --git a/pkg/gardenlet/controller/lease/add.go b/pkg/gardenlet/controller/lease/add.go
new file mode 100644
index 00000000000..cebb1c05fc4
--- /dev/null
+++ b/pkg/gardenlet/controller/lease/add.go
@@ -0,0 +1,49 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package lease
+
+import (
+ "time"
+
+ "k8s.io/client-go/util/workqueue"
+ "k8s.io/utils/clock"
+ "sigs.k8s.io/controller-runtime/pkg/builder"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/cluster"
+ "sigs.k8s.io/controller-runtime/pkg/controller"
+ "sigs.k8s.io/controller-runtime/pkg/handler"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+ "sigs.k8s.io/controller-runtime/pkg/predicate"
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
+ "sigs.k8s.io/controller-runtime/pkg/source"
+
+ predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
+)
+
+// AddToManager adds Reconciler to the given manager.
+func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster cluster.Cluster, controllerNamePrefix string, predicates ...predicate.Predicate) error {
+ if r.GardenClient == nil {
+ r.GardenClient = gardenCluster.GetClient()
+ }
+ if r.Clock == nil {
+ r.Clock = clock.RealClock{}
+ }
+
+ return builder.
+ ControllerManagedBy(mgr).
+ Named(controllerNamePrefix + "-lease").
+ WithOptions(controller.Options{
+ MaxConcurrentReconciles: 1,
+ RateLimiter: workqueue.NewTypedItemExponentialFailureRateLimiter[reconcile.Request](time.Millisecond, 2*time.Second),
+ ReconciliationTimeout: time.Duration(r.LeaseResyncSeconds) * time.Second,
+ }).
+ WatchesRawSource(source.Kind[client.Object](
+ gardenCluster.GetCache(),
+ r.NewObjectFunc(),
+ &handler.EnqueueRequestForObject{},
+ append([]predicate.Predicate{predicateutils.ForEventTypes(predicateutils.Create)}, predicates...)...,
+ )).
+ Complete(r)
+}
diff --git a/pkg/gardenlet/controller/seed/lease/lease_suite_test.go b/pkg/gardenlet/controller/lease/lease_suite_test.go
similarity index 100%
rename from pkg/gardenlet/controller/seed/lease/lease_suite_test.go
rename to pkg/gardenlet/controller/lease/lease_suite_test.go
diff --git a/pkg/gardenlet/controller/lease/reconciler.go b/pkg/gardenlet/controller/lease/reconciler.go
new file mode 100644
index 00000000000..d1d559b790d
--- /dev/null
+++ b/pkg/gardenlet/controller/lease/reconciler.go
@@ -0,0 +1,142 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package lease
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "time"
+
+ coordinationv1 "k8s.io/api/coordination/v1"
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/rest"
+ "k8s.io/utils/clock"
+ "k8s.io/utils/ptr"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
+ logf "sigs.k8s.io/controller-runtime/pkg/log"
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
+
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
+ "github.com/gardener/gardener/pkg/controllerutils"
+ "github.com/gardener/gardener/pkg/healthz"
+)
+
+// Reconciler reconciles resources and updates a corresponding heartbeat Lease object in the garden cluster when the
+// connection to the runtime cluster succeeds.
+type Reconciler struct {
+ GardenClient client.Client
+ RuntimeRESTClient rest.Interface
+
+ NewObjectFunc func() client.Object
+ GetObjectConditions func(client.Object) []gardencorev1beta1.Condition
+ SetObjectConditions func(client.Object, []gardencorev1beta1.Condition)
+
+ LeaseResyncSeconds int32
+ LeaseNamePrefix string
+ LeaseNamespace *string
+ Clock clock.Clock
+ HealthManager healthz.Manager
+}
+
+// Reconcile reconciles resources and updates a corresponding heartbeat Lease object in the garden cluster when the
+// connection to the runtime cluster succeeds.
+func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
+ log := logf.FromContext(ctx)
+
+ obj := r.NewObjectFunc()
+ if err := r.GardenClient.Get(ctx, request.NamespacedName, obj); err != nil {
+ if apierrors.IsNotFound(err) {
+ log.V(1).Info("Object is gone, stop reconciling")
+ return reconcile.Result{}, nil
+ }
+ return reconcile.Result{}, fmt.Errorf("error retrieving object from store: %w", err)
+ }
+
+ if err := CheckConnection(ctx, r.RuntimeRESTClient); err != nil {
+ r.HealthManager.Set(false)
+ return reconcile.Result{}, fmt.Errorf("cannot establish connection with runtime cluster: %w", err)
+ }
+
+ if err := r.renewLease(ctx, obj); err != nil {
+ r.HealthManager.Set(false)
+ return reconcile.Result{}, err
+ }
+
+ r.HealthManager.Set(true)
+ return reconcile.Result{RequeueAfter: time.Duration(r.LeaseResyncSeconds) * time.Second}, r.maintainGardenletReadyCondition(ctx, obj)
+}
+
+// CheckConnection is a function which checks the connection to the runtime cluster.
+// Exposed for testing.
+var CheckConnection = func(ctx context.Context, client rest.Interface) error {
+ result := client.Get().AbsPath("/healthz").Do(ctx)
+ if result.Error() != nil {
+ return fmt.Errorf("failed to execute call to Kubernetes API Server: %v", result.Error())
+ }
+
+ var statusCode int
+ result.StatusCode(&statusCode)
+ if statusCode != http.StatusOK {
+ return fmt.Errorf("API Server returned unexpected status code: %d", statusCode)
+ }
+
+ return nil
+}
+
+func (r *Reconciler) renewLease(ctx context.Context, obj client.Object) error {
+ lease := &coordinationv1.Lease{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: r.LeaseNamePrefix + obj.GetName(),
+ Namespace: ptr.Deref(r.LeaseNamespace, obj.GetNamespace()),
+ },
+ }
+
+ gvk, err := apiutil.GVKForObject(obj, r.GardenClient.Scheme())
+ if err != nil {
+ return fmt.Errorf("failed determining group/version/kind for object: %w", err)
+ }
+
+ _, err = controllerutils.CreateOrGetAndMergePatch(ctx, r.GardenClient, lease, func() error {
+ lease.OwnerReferences = []metav1.OwnerReference{{
+ APIVersion: gvk.GroupVersion().String(),
+ Kind: gvk.Kind,
+ Name: obj.GetName(),
+ UID: obj.GetUID(),
+ }}
+ lease.Spec.HolderIdentity = ptr.To(obj.GetName())
+ lease.Spec.LeaseDurationSeconds = &r.LeaseResyncSeconds
+ lease.Spec.RenewTime = &metav1.MicroTime{Time: r.Clock.Now()}
+ return nil
+ })
+ return err
+}
+
+func (r *Reconciler) maintainGardenletReadyCondition(ctx context.Context, obj client.Object) error {
+ bldr, err := helper.NewConditionBuilder(gardencorev1beta1.GardenletReady)
+ if err != nil {
+ return err
+ }
+
+ if oldCondition := helper.GetCondition(r.GetObjectConditions(obj), gardencorev1beta1.GardenletReady); oldCondition != nil {
+ bldr.WithOldCondition(*oldCondition)
+ }
+ bldr.WithStatus(gardencorev1beta1.ConditionTrue)
+ bldr.WithReason("GardenletReady")
+ bldr.WithMessage("Gardenlet is posting ready status.")
+ bldr.WithClock(r.Clock)
+
+ newCondition, needsUpdate := bldr.Build()
+ if !needsUpdate {
+ return nil
+ }
+
+ patch := client.StrategicMergeFrom(obj.DeepCopyObject().(client.Object))
+ r.SetObjectConditions(obj, helper.MergeConditions(r.GetObjectConditions(obj), newCondition))
+ return r.GardenClient.Status().Patch(ctx, obj, patch)
+}
diff --git a/pkg/gardenlet/controller/seed/lease/reconciler_test.go b/pkg/gardenlet/controller/lease/reconciler_test.go
similarity index 88%
rename from pkg/gardenlet/controller/seed/lease/reconciler_test.go
rename to pkg/gardenlet/controller/lease/reconciler_test.go
index 82579e97d2e..0716a0fcda3 100644
--- a/pkg/gardenlet/controller/seed/lease/reconciler_test.go
+++ b/pkg/gardenlet/controller/lease/reconciler_test.go
@@ -29,28 +29,26 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/client/kubernetes"
- gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
- . "github.com/gardener/gardener/pkg/gardenlet/controller/seed/lease"
+ . "github.com/gardener/gardener/pkg/gardenlet/controller/lease"
"github.com/gardener/gardener/pkg/healthz"
. "github.com/gardener/gardener/pkg/utils/test/matchers"
)
var _ = Describe("LeaseReconciler", func() {
var (
- ctx context.Context
- clock clock.Clock
- gardenClient client.Client
- seedRESTClient *fakerestclient.RESTClient
- healthManager healthz.Manager
+ ctx context.Context
+ clock clock.Clock
+ gardenClient client.Client
+ runtimeRESTClient *fakerestclient.RESTClient
+ healthManager healthz.Manager
seed *gardencorev1beta1.Seed
expectedCondition *gardencorev1beta1.Condition
expectedLease *coordinationv1.Lease
namespace = "gardener-system-seed-lease"
- request reconcile.Request
- reconciler *Reconciler
- controllerConfig gardenletconfigv1alpha1.SeedControllerConfiguration
+ request reconcile.Request
+ reconciler *Reconciler
)
BeforeEach(func() {
@@ -85,18 +83,13 @@ var _ = Describe("LeaseReconciler", func() {
}
gardenClient = fakeclient.NewClientBuilder().WithScheme(kubernetes.GardenScheme).WithObjects(seed).WithStatusSubresource(&gardencorev1beta1.Seed{}).Build()
- seedRESTClient = &fakerestclient.RESTClient{
+ runtimeRESTClient = &fakerestclient.RESTClient{
NegotiatedSerializer: serializer.NewCodecFactory(kubernetes.GardenScheme).WithoutConversion(),
Resp: &http.Response{
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader("")),
},
}
-
- controllerConfig = gardenletconfigv1alpha1.SeedControllerConfiguration{
- LeaseResyncSeconds: ptr.To[int32](2),
- LeaseResyncMissThreshold: ptr.To[int32](10),
- }
})
JustBeforeEach(func() {
@@ -104,12 +97,19 @@ var _ = Describe("LeaseReconciler", func() {
Expect(healthManager.Start(ctx)).To(Succeed())
reconciler = &Reconciler{
- GardenClient: gardenClient,
- SeedRESTClient: seedRESTClient,
- Config: controllerConfig,
- Clock: clock,
- HealthManager: healthManager,
- LeaseNamespace: namespace,
+ GardenClient: gardenClient,
+ RuntimeRESTClient: runtimeRESTClient,
+ NewObjectFunc: func() client.Object { return &gardencorev1beta1.Seed{} },
+ GetObjectConditions: func(obj client.Object) []gardencorev1beta1.Condition {
+ return obj.(*gardencorev1beta1.Seed).Status.Conditions
+ },
+ SetObjectConditions: func(obj client.Object, conditions []gardencorev1beta1.Condition) {
+ obj.(*gardencorev1beta1.Seed).Status.Conditions = conditions
+ },
+ LeaseResyncSeconds: 2,
+ LeaseNamespace: &namespace,
+ Clock: clock,
+ HealthManager: healthManager,
}
})
@@ -153,7 +153,7 @@ var _ = Describe("LeaseReconciler", func() {
expectedCondition = gardenletReadyCondition(clock)
expectedLease.Spec.LeaseDurationSeconds = ptr.To[int32](3)
- reconciler.Config.LeaseResyncSeconds = ptr.To[int32](3)
+ reconciler.LeaseResyncSeconds = 3
request = reconcile.Request{NamespacedName: client.ObjectKeyFromObject(seed)}
Expect(reconciler.Reconcile(ctx, request)).To(Equal(reconcile.Result{RequeueAfter: 3 * time.Second}))
@@ -161,7 +161,7 @@ var _ = Describe("LeaseReconciler", func() {
})
It("should fail if connection to Seed fails", func() {
- seedRESTClient.Resp.StatusCode = http.StatusInternalServerError
+ runtimeRESTClient.Resp.StatusCode = http.StatusInternalServerError
expectedLease = nil
expectedCondition = nil
diff --git a/pkg/gardenlet/controller/seed/add.go b/pkg/gardenlet/controller/seed/add.go
index 8e872e04ae6..63c29ef2000 100644
--- a/pkg/gardenlet/controller/seed/add.go
+++ b/pkg/gardenlet/controller/seed/add.go
@@ -8,6 +8,7 @@ import (
"fmt"
"os"
+ "k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/cluster"
"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -50,12 +51,7 @@ func AddToManager(
return fmt.Errorf("failed adding care reconciler: %w", err)
}
- if err := (&lease.Reconciler{
- SeedRESTClient: seedClientSet.RESTClient(),
- Config: *cfg.Controllers.Seed,
- HealthManager: healthManager,
- SeedName: cfg.SeedConfig.Name,
- }).AddToManager(mgr, gardenCluster); err != nil {
+ if err := lease.AddToManager(mgr, gardenCluster, seedClientSet.RESTClient(), *cfg.Controllers.Seed, healthManager, cfg.SeedConfig.Name, nil, ptr.To(gardencorev1beta1.GardenerSeedLeaseNamespace)); err != nil {
return fmt.Errorf("failed adding lease reconciler: %w", err)
}
diff --git a/pkg/gardenlet/controller/seed/lease/add.go b/pkg/gardenlet/controller/seed/lease/add.go
index f29ebd7682c..928edc19c06 100644
--- a/pkg/gardenlet/controller/seed/lease/add.go
+++ b/pkg/gardenlet/controller/seed/lease/add.go
@@ -5,52 +5,44 @@
package lease
import (
- "time"
-
- "k8s.io/client-go/util/workqueue"
+ "k8s.io/client-go/rest"
"k8s.io/utils/clock"
- "sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/cluster"
- "sigs.k8s.io/controller-runtime/pkg/controller"
- "sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/manager"
- "sigs.k8s.io/controller-runtime/pkg/reconcile"
- "sigs.k8s.io/controller-runtime/pkg/source"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
predicateutils "github.com/gardener/gardener/pkg/controllerutils/predicate"
+ gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
+ "github.com/gardener/gardener/pkg/gardenlet/controller/lease"
+ "github.com/gardener/gardener/pkg/healthz"
)
-// ControllerName is the name of this controller.
-const ControllerName = "seed-lease"
+// AddToManager adds the seed-lease controller to the given manager.
+func AddToManager(
+ mgr manager.Manager,
+ gardenCluster cluster.Cluster,
+ seedRESTClient rest.Interface,
+ config gardenletconfigv1alpha1.SeedControllerConfiguration,
+ healthManager healthz.Manager,
+ seedName string,
+ clock clock.Clock,
+ leaseNamespace *string,
+) error {
+ return (&lease.Reconciler{
+ RuntimeRESTClient: seedRESTClient,
+ HealthManager: healthManager,
+ Clock: clock,
-// AddToManager adds Reconciler to the given manager.
-func (r *Reconciler) AddToManager(mgr manager.Manager, gardenCluster cluster.Cluster) error {
- if r.GardenClient == nil {
- r.GardenClient = gardenCluster.GetClient()
- }
- if r.Clock == nil {
- r.Clock = clock.RealClock{}
- }
- if r.LeaseNamespace == "" {
- r.LeaseNamespace = gardencorev1beta1.GardenerSeedLeaseNamespace
- }
+ NewObjectFunc: func() client.Object { return &gardencorev1beta1.Seed{} },
+ GetObjectConditions: func(obj client.Object) []gardencorev1beta1.Condition {
+ return obj.(*gardencorev1beta1.Seed).Status.Conditions
+ },
+ SetObjectConditions: func(obj client.Object, conditions []gardencorev1beta1.Condition) {
+ obj.(*gardencorev1beta1.Seed).Status.Conditions = conditions
+ },
- return builder.
- ControllerManagedBy(mgr).
- Named(ControllerName).
- WithOptions(controller.Options{
- MaxConcurrentReconciles: 1,
- RateLimiter: workqueue.NewTypedItemExponentialFailureRateLimiter[reconcile.Request](time.Millisecond, 2*time.Second),
- ReconciliationTimeout: time.Duration(*r.Config.LeaseResyncSeconds) * time.Second,
- }).
- WatchesRawSource(
- source.Kind[client.Object](gardenCluster.GetCache(),
- &gardencorev1beta1.Seed{},
- &handler.EnqueueRequestForObject{},
- predicateutils.HasName(r.SeedName),
- predicateutils.ForEventTypes(predicateutils.Create)),
- ).
- Complete(r)
+ LeaseNamespace: leaseNamespace,
+ LeaseResyncSeconds: *config.LeaseResyncSeconds,
+ }).AddToManager(mgr, gardenCluster, "seed", predicateutils.HasName(seedName))
}
diff --git a/pkg/gardenlet/controller/seed/lease/reconciler.go b/pkg/gardenlet/controller/seed/lease/reconciler.go
deleted file mode 100644
index 6ed700c6063..00000000000
--- a/pkg/gardenlet/controller/seed/lease/reconciler.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
-//
-// SPDX-License-Identifier: Apache-2.0
-
-package lease
-
-import (
- "context"
- "fmt"
- "net/http"
- "time"
-
- coordinationv1 "k8s.io/api/coordination/v1"
- apierrors "k8s.io/apimachinery/pkg/api/errors"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/client-go/rest"
- "k8s.io/utils/clock"
- "k8s.io/utils/ptr"
- "sigs.k8s.io/controller-runtime/pkg/client"
- logf "sigs.k8s.io/controller-runtime/pkg/log"
- "sigs.k8s.io/controller-runtime/pkg/reconcile"
-
- gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
- "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
- "github.com/gardener/gardener/pkg/controllerutils"
- gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/healthz"
-)
-
-// Reconciler reconciles Seed resources and updates the heartbeat Lease object in the garden cluster when the connection
-// to the seed cluster succeeds.
-type Reconciler struct {
- GardenClient client.Client
- SeedRESTClient rest.Interface
- Config gardenletconfigv1alpha1.SeedControllerConfiguration
- Clock clock.Clock
- HealthManager healthz.Manager
- LeaseNamespace string
- SeedName string
-}
-
-// Reconcile reconciles Seed resources and updates the heartbeat Lease object in the garden cluster when the connection
-// to the seed cluster succeeds.
-func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
- log := logf.FromContext(ctx)
-
- seed := &gardencorev1beta1.Seed{}
- if err := r.GardenClient.Get(ctx, request.NamespacedName, seed); err != nil {
- if apierrors.IsNotFound(err) {
- log.V(1).Info("Object is gone, stop reconciling")
- return reconcile.Result{}, nil
- }
- return reconcile.Result{}, fmt.Errorf("error retrieving object from store: %w", err)
- }
-
- if err := CheckSeedConnection(ctx, r.SeedRESTClient); err != nil {
- r.HealthManager.Set(false)
- return reconcile.Result{}, fmt.Errorf("cannot establish connection with Seed: %w", err)
- }
-
- if err := r.renewLeaseForSeed(ctx, seed); err != nil {
- r.HealthManager.Set(false)
- return reconcile.Result{}, err
- }
-
- r.HealthManager.Set(true)
- return reconcile.Result{RequeueAfter: time.Duration(*r.Config.LeaseResyncSeconds) * time.Second}, r.maintainGardenletReadyCondition(ctx, seed)
-}
-
-// CheckSeedConnection is a function which checks the connection to the seed.
-// Exposed for testing.
-var CheckSeedConnection = func(ctx context.Context, client rest.Interface) error {
- result := client.Get().AbsPath("/healthz").Do(ctx)
- if result.Error() != nil {
- return fmt.Errorf("failed to execute call to Kubernetes API Server: %v", result.Error())
- }
-
- var statusCode int
- result.StatusCode(&statusCode)
- if statusCode != http.StatusOK {
- return fmt.Errorf("API Server returned unexpected status code: %d", statusCode)
- }
-
- return nil
-}
-
-func (r *Reconciler) renewLeaseForSeed(ctx context.Context, seed *gardencorev1beta1.Seed) error {
- lease := &coordinationv1.Lease{
- ObjectMeta: metav1.ObjectMeta{
- Name: seed.Name,
- Namespace: r.LeaseNamespace,
- },
- }
-
- _, err := controllerutils.CreateOrGetAndMergePatch(ctx, r.GardenClient, lease, func() error {
- lease.OwnerReferences = []metav1.OwnerReference{{
- APIVersion: gardencorev1beta1.SchemeGroupVersion.String(),
- Kind: "Seed",
- Name: seed.GetName(),
- UID: seed.GetUID(),
- }}
- lease.Spec.HolderIdentity = ptr.To(seed.Name)
- lease.Spec.LeaseDurationSeconds = r.Config.LeaseResyncSeconds
- lease.Spec.RenewTime = &metav1.MicroTime{Time: r.Clock.Now()}
- return nil
- })
- return err
-}
-
-func (r *Reconciler) maintainGardenletReadyCondition(ctx context.Context, seed *gardencorev1beta1.Seed) error {
- bldr, err := helper.NewConditionBuilder(gardencorev1beta1.SeedGardenletReady)
- if err != nil {
- return err
- }
-
- if oldCondition := helper.GetCondition(seed.Status.Conditions, gardencorev1beta1.SeedGardenletReady); oldCondition != nil {
- bldr.WithOldCondition(*oldCondition)
- }
- bldr.WithStatus(gardencorev1beta1.ConditionTrue)
- bldr.WithReason("GardenletReady")
- bldr.WithMessage("Gardenlet is posting ready status.")
- bldr.WithClock(r.Clock)
-
- newCondition, needsUpdate := bldr.Build()
- if !needsUpdate {
- return nil
- }
-
- patch := client.StrategicMergeFrom(seed.DeepCopy())
- seed.Status.Conditions = helper.MergeConditions(seed.Status.Conditions, newCondition)
- return r.GardenClient.Status().Patch(ctx, seed, patch)
-}
diff --git a/pkg/gardenlet/controller/seed/seed/reconciler.go b/pkg/gardenlet/controller/seed/seed/reconciler.go
index ccb94189b35..caca10fe39b 100644
--- a/pkg/gardenlet/controller/seed/seed/reconciler.go
+++ b/pkg/gardenlet/controller/seed/seed/reconciler.go
@@ -221,7 +221,7 @@ func (r *Reconciler) updateStatusOperationSuccess(ctx context.Context, seed *gar
switch cond.Type {
case gardencorev1beta1.SeedBackupBucketsReady,
gardencorev1beta1.SeedExtensionsReady,
- gardencorev1beta1.SeedGardenletReady,
+ gardencorev1beta1.GardenletReady,
gardencorev1beta1.SeedSystemComponentsHealthy:
if cond.Status != gardencorev1beta1.ConditionFalse {
seed.Status.Conditions[i].Status = gardencorev1beta1.ConditionProgressing
diff --git a/pkg/gardenlet/controller/shoot/add.go b/pkg/gardenlet/controller/shoot/add.go
index ab0b22b9708..5d4e9ea6079 100644
--- a/pkg/gardenlet/controller/shoot/add.go
+++ b/pkg/gardenlet/controller/shoot/add.go
@@ -21,9 +21,12 @@ import (
"github.com/gardener/gardener/pkg/client/kubernetes/clientmap"
gardenletconfigv1alpha1 "github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1"
"github.com/gardener/gardener/pkg/gardenlet/controller/shoot/care"
+ "github.com/gardener/gardener/pkg/gardenlet/controller/shoot/lease"
"github.com/gardener/gardener/pkg/gardenlet/controller/shoot/shoot"
"github.com/gardener/gardener/pkg/gardenlet/controller/shoot/state"
"github.com/gardener/gardener/pkg/gardenlet/controller/shoot/status"
+ "github.com/gardener/gardener/pkg/healthz"
+ "github.com/gardener/gardener/pkg/utils/gardener/gardenlet"
)
// AddToManager adds all Shoot controllers to the given manager.
@@ -37,6 +40,7 @@ func AddToManager(
cfg gardenletconfigv1alpha1.GardenletConfiguration,
identity *gardencorev1beta1.Gardener,
gardenClusterIdentity string,
+ healthManager healthz.Manager,
) error {
var responsibleForUnmanagedSeed bool
if err := gardenCluster.GetAPIReader().Get(ctx, client.ObjectKey{Name: cfg.SeedConfig.Name, Namespace: v1beta1constants.GardenNamespace}, &seedmanagementv1alpha1.ManagedSeed{}); err != nil {
@@ -90,5 +94,11 @@ func AddToManager(
}
}
+ if gardenlet.IsResponsibleForSelfHostedShoot() {
+ if err := lease.AddToManager(mgr, gardenCluster, seedClientSet.RESTClient(), healthManager, nil); err != nil {
+ return fmt.Errorf("failed adding lease reconciler: %w", err)
+ }
+ }
+
return nil
}
diff --git a/pkg/gardenlet/controller/shoot/lease/add.go b/pkg/gardenlet/controller/shoot/lease/add.go
new file mode 100644
index 00000000000..253a7236a71
--- /dev/null
+++ b/pkg/gardenlet/controller/shoot/lease/add.go
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package lease
+
+import (
+ "k8s.io/client-go/rest"
+ "k8s.io/utils/clock"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/cluster"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ "github.com/gardener/gardener/pkg/gardenlet/controller/lease"
+ "github.com/gardener/gardener/pkg/healthz"
+ "github.com/gardener/gardener/pkg/utils/gardener/gardenlet"
+)
+
+// AddToManager adds the shoot-lease controller to the given manager.
+func AddToManager(mgr manager.Manager, gardenCluster cluster.Cluster, shootRESTClient rest.Interface, healthManager healthz.Manager, clock clock.Clock) error {
+ return (&lease.Reconciler{
+ RuntimeRESTClient: shootRESTClient,
+ HealthManager: healthManager,
+ Clock: clock,
+
+ NewObjectFunc: func() client.Object { return &gardencorev1beta1.Shoot{} },
+ GetObjectConditions: func(obj client.Object) []gardencorev1beta1.Condition {
+ return obj.(*gardencorev1beta1.Shoot).Status.Conditions
+ },
+ SetObjectConditions: func(obj client.Object, conditions []gardencorev1beta1.Condition) {
+ obj.(*gardencorev1beta1.Shoot).Status.Conditions = conditions
+ },
+
+ LeaseNamePrefix: gardenlet.ResourcePrefixSelfHostedShoot,
+ LeaseResyncSeconds: 2,
+ }).AddToManager(mgr, gardenCluster, "shoot")
+}
diff --git a/pkg/scheduler/controller/shoot/reconciler.go b/pkg/scheduler/controller/shoot/reconciler.go
index 38470648b86..a0dcba7fd1b 100644
--- a/pkg/scheduler/controller/shoot/reconciler.go
+++ b/pkg/scheduler/controller/shoot/reconciler.go
@@ -634,7 +634,7 @@ func verifySeedReadiness(seed *gardencorev1beta1.Seed) bool {
return false
}
- if cond := v1beta1helper.GetCondition(seed.Status.Conditions, gardencorev1beta1.SeedGardenletReady); cond == nil || cond.Status != gardencorev1beta1.ConditionTrue {
+ if cond := v1beta1helper.GetCondition(seed.Status.Conditions, gardencorev1beta1.GardenletReady); cond == nil || cond.Status != gardencorev1beta1.ConditionTrue {
return false
}
diff --git a/pkg/scheduler/controller/shoot/reconciler_test.go b/pkg/scheduler/controller/shoot/reconciler_test.go
index fbec6dea541..e3edfaff2de 100644
--- a/pkg/scheduler/controller/shoot/reconciler_test.go
+++ b/pkg/scheduler/controller/shoot/reconciler_test.go
@@ -81,7 +81,7 @@ var _ = Describe("Scheduler_Control", func() {
Status: gardencorev1beta1.SeedStatus{
Conditions: []gardencorev1beta1.Condition{
{
- Type: gardencorev1beta1.SeedGardenletReady,
+ Type: gardencorev1beta1.GardenletReady,
Status: gardencorev1beta1.ConditionTrue,
},
},
@@ -871,7 +871,7 @@ var _ = Describe("Scheduler_Control", func() {
It("should fail because it cannot find a seed cluster due to gardenlet not ready", func() {
seed.Status.Conditions = []gardencorev1beta1.Condition{
{
- Type: gardencorev1beta1.SeedGardenletReady,
+ Type: gardencorev1beta1.GardenletReady,
Status: gardencorev1beta1.ConditionFalse,
},
}
@@ -1139,7 +1139,7 @@ var _ = DescribeTable("condition is false",
},
Status: gardencorev1beta1.SeedStatus{
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedBackupBucketsReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedExtensionsReady, Status: gardencorev1beta1.ConditionTrue},
},
@@ -1161,8 +1161,8 @@ var _ = DescribeTable("condition is false",
Expect(verifySeedReadiness(seed)).To(expected)
},
- Entry("SeedGardenletReady is missing", gardencorev1beta1.SeedGardenletReady, true, true, BeFalse()),
- Entry("SeedGardenletReady is false", gardencorev1beta1.SeedGardenletReady, false, true, BeFalse()),
+ Entry("GardenletReady is missing", gardencorev1beta1.GardenletReady, true, true, BeFalse()),
+ Entry("GardenletReady is false", gardencorev1beta1.GardenletReady, false, true, BeFalse()),
Entry("SeedBackupBucketsReady is missing", gardencorev1beta1.SeedBackupBucketsReady, true, true, BeFalse()),
Entry("SeedBackupBucketsReady is missing but no backup specified", gardencorev1beta1.SeedBackupBucketsReady, true, false, BeTrue()),
Entry("SeedBackupBucketsReady is false", gardencorev1beta1.SeedBackupBucketsReady, false, true, BeFalse()),
diff --git a/pkg/utils/graph/eventhandler_seed.go b/pkg/utils/graph/eventhandler_seed.go
index 60148f0a02c..9c4a95e5b9f 100644
--- a/pkg/utils/graph/eventhandler_seed.go
+++ b/pkg/utils/graph/eventhandler_seed.go
@@ -52,7 +52,7 @@ func (g *graph) setupSeedWatch(ctx context.Context, informer cache.Informer) err
g.handleSeedCreateOrUpdate(newSeed)
}
- newGardenletReadyCondition := v1beta1helper.GetCondition(newSeed.Status.Conditions, gardencorev1beta1.SeedGardenletReady)
+ newGardenletReadyCondition := v1beta1helper.GetCondition(newSeed.Status.Conditions, gardencorev1beta1.GardenletReady)
// When the GardenletReady condition transitions to 'Unknown' then the client certificate might be expired.
// Hence, check if seed belongs to a ManagedSeed and reconcile it to potentially allow re-bootstrapping it.
diff --git a/pkg/utils/graph/eventhandler_shoot.go b/pkg/utils/graph/eventhandler_shoot.go
index a102356bb84..67615cb1749 100644
--- a/pkg/utils/graph/eventhandler_shoot.go
+++ b/pkg/utils/graph/eventhandler_shoot.go
@@ -19,6 +19,7 @@ import (
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
gardenerutils "github.com/gardener/gardener/pkg/utils/gardener"
+ "github.com/gardener/gardener/pkg/utils/gardener/gardenlet"
)
func (g *graph) setupShootWatch(ctx context.Context, informer cache.Informer) error {
@@ -106,7 +107,9 @@ func (g *graph) HandleShootCreateOrUpdate(ctx context.Context, shoot *gardencore
g.deleteAllIncomingEdges(VertexTypeSecretBinding, VertexTypeShoot, shoot.Namespace, shoot.Name)
g.deleteAllIncomingEdges(VertexTypeCredentialsBinding, VertexTypeShoot, shoot.Namespace, shoot.Name)
g.deleteAllIncomingEdges(VertexTypeShootState, VertexTypeShoot, shoot.Namespace, shoot.Name)
- if !g.forSelfHostedShoots {
+ if g.forSelfHostedShoots {
+ g.deleteAllIncomingEdges(VertexTypeLease, VertexTypeShoot, shoot.Namespace, shoot.Name)
+ } else {
g.deleteAllOutgoingEdges(VertexTypeShoot, shoot.Namespace, shoot.Name, VertexTypeSeed)
}
@@ -237,6 +240,11 @@ func (g *graph) HandleShootCreateOrUpdate(ctx context.Context, shoot *gardencore
}
}
}
+
+ if g.forSelfHostedShoots {
+ leaseVertex := g.getOrCreateVertex(VertexTypeLease, shoot.Namespace, gardenlet.ResourcePrefixSelfHostedShoot+shoot.Name)
+ g.addEdge(leaseVertex, shootVertex)
+ }
}
func (g *graph) handleShootDelete(shoot *gardencorev1beta1.Shoot) {
diff --git a/pkg/utils/graph/graph_test.go b/pkg/utils/graph/graph_test.go
index 3a928c11416..a9a2bbee202 100644
--- a/pkg/utils/graph/graph_test.go
+++ b/pkg/utils/graph/graph_test.go
@@ -2688,8 +2688,8 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
It("should behave as expected for gardencorev1beta1.Shoot", func() {
By("Add")
fakeInformerShoot.Add(shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(22))
- Expect(graph.graph.Edges().Len()).To(Equal(21))
+ Expect(graph.graph.Nodes().Len()).To(Equal(23))
+ Expect(graph.graph.Edges().Len()).To(Equal(22))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", *shoot1.Spec.CloudProfileName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeNamespacedCloudProfile, shoot1.Namespace, shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
@@ -2712,6 +2712,7 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Add (with namespaced cloud profile)")
shoot1Copy := shoot1.DeepCopy()
@@ -2721,8 +2722,8 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Name: "namespaced-profile-1",
}
fakeInformerShoot.Add(shoot1Copy)
- Expect(graph.graph.Nodes().Len()).To(Equal(22))
- Expect(graph.graph.Edges().Len()).To(Equal(21))
+ Expect(graph.graph.Nodes().Len()).To(Equal(23))
+ Expect(graph.graph.Edges().Len()).To(Equal(22))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", *shoot1.Spec.CloudProfileName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
Expect(graph.HasPathFrom(VertexTypeNamespacedCloudProfile, shoot1.Namespace, shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
@@ -2746,13 +2747,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Add (secret binding is nil)")
shoot1Copy = shoot1.DeepCopy()
shoot1Copy.Spec.SecretBindingName = nil
fakeInformerShoot.Add(shoot1Copy)
- Expect(graph.graph.Nodes().Len()).To(Equal(21))
- Expect(graph.graph.Edges().Len()).To(Equal(20))
+ Expect(graph.graph.Nodes().Len()).To(Equal(22))
+ Expect(graph.graph.Edges().Len()).To(Equal(21))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", *shoot1.Spec.CloudProfileName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCredentialsBinding, shoot1.Namespace, *shoot1.Spec.CredentialsBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -2773,13 +2775,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Add (credentials binding is nil)")
shoot1Copy = shoot1.DeepCopy()
shoot1Copy.Spec.CredentialsBindingName = nil
fakeInformerShoot.Add(shoot1Copy)
- Expect(graph.graph.Nodes().Len()).To(Equal(21))
- Expect(graph.graph.Edges().Len()).To(Equal(20))
+ Expect(graph.graph.Nodes().Len()).To(Equal(22))
+ Expect(graph.graph.Edges().Len()).To(Equal(21))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", *shoot1.Spec.CloudProfileName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -2800,13 +2803,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (cloud profile name)")
shoot1Copy = shoot1.DeepCopy()
shoot1.Spec.CloudProfile = &gardencorev1beta1.CloudProfileReference{Name: "foo", Kind: "CloudProfile"}
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(22))
- Expect(graph.graph.Edges().Len()).To(Equal(21))
+ Expect(graph.graph.Nodes().Len()).To(Equal(23))
+ Expect(graph.graph.Edges().Len()).To(Equal(22))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", *shoot1Copy.Spec.CloudProfileName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -2830,13 +2834,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (namespaced cloud profile)")
shoot1Copy = shoot1.DeepCopy()
shoot1Copy.Spec.CloudProfile = &gardencorev1beta1.CloudProfileReference{Name: "namespaced-profile", Kind: "NamespacedCloudProfile"}
fakeInformerShoot.Update(shoot1, shoot1Copy)
- Expect(graph.graph.Nodes().Len()).To(Equal(22))
- Expect(graph.graph.Edges().Len()).To(Equal(21))
+ Expect(graph.graph.Nodes().Len()).To(Equal(23))
+ Expect(graph.graph.Edges().Len()).To(Equal(22))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", *shoot1Copy.Spec.CloudProfileName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1Copy.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
@@ -2861,13 +2866,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (secret binding name)")
shoot1Copy = shoot1.DeepCopy()
shoot1.Spec.SecretBindingName = ptr.To("bar")
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(22))
- Expect(graph.graph.Edges().Len()).To(Equal(21))
+ Expect(graph.graph.Nodes().Len()).To(Equal(23))
+ Expect(graph.graph.Edges().Len()).To(Equal(22))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1Copy.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
@@ -2890,13 +2896,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (credentials binding name)")
shoot1Copy = shoot1.DeepCopy()
shoot1.Spec.CredentialsBindingName = ptr.To("bar")
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(22))
- Expect(graph.graph.Edges().Len()).To(Equal(21))
+ Expect(graph.graph.Nodes().Len()).To(Equal(23))
+ Expect(graph.graph.Edges().Len()).To(Equal(22))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -2919,13 +2926,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (audit policy config map name)")
shoot1Copy = shoot1.DeepCopy()
shoot1.Spec.Kubernetes.KubeAPIServer.AuditConfig = nil
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(21))
- Expect(graph.graph.Edges().Len()).To(Equal(20))
+ Expect(graph.graph.Nodes().Len()).To(Equal(22))
+ Expect(graph.graph.Edges().Len()).To(Equal(21))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -2947,13 +2955,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (structured authentication config map name)")
shoot1Copy = shoot1.DeepCopy()
shoot1.Spec.Kubernetes.KubeAPIServer.StructuredAuthentication = nil
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(20))
- Expect(graph.graph.Edges().Len()).To(Equal(19))
+ Expect(graph.graph.Nodes().Len()).To(Equal(21))
+ Expect(graph.graph.Edges().Len()).To(Equal(20))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -2975,13 +2984,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (structured authorization kubeconfig secrets)")
shoot1Copy = shoot1.DeepCopy()
shoot1.Spec.Kubernetes.KubeAPIServer.StructuredAuthorization.Kubeconfigs = nil
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(19))
- Expect(graph.graph.Edges().Len()).To(Equal(18))
+ Expect(graph.graph.Nodes().Len()).To(Equal(20))
+ Expect(graph.graph.Edges().Len()).To(Equal(19))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -3003,13 +3013,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (structured authorization config map name and kubeconfig secrets)")
shoot1Copy = shoot1.DeepCopy()
shoot1.Spec.Kubernetes.KubeAPIServer.StructuredAuthorization = nil
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(18))
- Expect(graph.graph.Edges().Len()).To(Equal(17))
+ Expect(graph.graph.Nodes().Len()).To(Equal(19))
+ Expect(graph.graph.Edges().Len()).To(Equal(18))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -3031,13 +3042,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (dns provider secrets)")
shoot1Copy = shoot1.DeepCopy()
shoot1.Spec.DNS = nil
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(16))
- Expect(graph.graph.Edges().Len()).To(Equal(15))
+ Expect(graph.graph.Nodes().Len()).To(Equal(17))
+ Expect(graph.graph.Edges().Len()).To(Equal(16))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -3059,13 +3071,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Update (resources)")
shoot1Copy = shoot1.DeepCopy()
shoot1.Spec.Resources = nil
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(14))
- Expect(graph.graph.Edges().Len()).To(Equal(13))
+ Expect(graph.graph.Nodes().Len()).To(Equal(15))
+ Expect(graph.graph.Edges().Len()).To(Equal(14))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -3087,13 +3100,14 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Remove managed issuer annotation")
shoot1Copy = shoot1.DeepCopy()
shoot1.Annotations = map[string]string{}
fakeInformerShoot.Update(shoot1Copy, shoot1)
- Expect(graph.graph.Nodes().Len()).To(Equal(13))
- Expect(graph.graph.Edges().Len()).To(Equal(12))
+ Expect(graph.graph.Nodes().Len()).To(Equal(14))
+ Expect(graph.graph.Edges().Len()).To(Equal(13))
Expect(graph.HasPathFrom(VertexTypeNamespace, "", shoot1.Namespace, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeCloudProfile, "", shoot1.Spec.CloudProfile.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeSecretBinding, shoot1.Namespace, *shoot1.Spec.SecretBindingName, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
@@ -3115,6 +3129,7 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeTrue())
By("Delete")
fakeInformerShoot.Delete(shoot1)
@@ -3142,6 +3157,7 @@ Foj/rmOanFj5g6QF3GRDrqaNc1GNEXDU6fW7JsTx6+Anj1M/aDNxOXYqIqUN0s3d
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCACluster, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
Expect(graph.HasPathFrom(VertexTypeConfigMap, shoot1.Namespace, shoot1ConfigMapNameCAKubelet, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
Expect(graph.HasPathFrom(VertexTypeShootState, shoot1.Namespace, shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
+ Expect(graph.HasPathFrom(VertexTypeLease, shoot1.Namespace, "self-hosted-shoot-"+shoot1.Name, VertexTypeShoot, shoot1.Namespace, shoot1.Name)).To(BeFalse())
})
})
diff --git a/pkg/utils/kubernetes/health/seed.go b/pkg/utils/kubernetes/health/seed.go
index 72565ea20ec..48c3e707479 100644
--- a/pkg/utils/kubernetes/health/seed.go
+++ b/pkg/utils/kubernetes/health/seed.go
@@ -15,7 +15,7 @@ import (
var (
trueSeedConditionTypes = []gardencorev1beta1.ConditionType{
- gardencorev1beta1.SeedGardenletReady,
+ gardencorev1beta1.GardenletReady,
gardencorev1beta1.SeedSystemComponentsHealthy,
}
)
diff --git a/pkg/utils/kubernetes/health/seed_test.go b/pkg/utils/kubernetes/health/seed_test.go
index 3be908c19e6..54493abca01 100644
--- a/pkg/utils/kubernetes/health/seed_test.go
+++ b/pkg/utils/kubernetes/health/seed_test.go
@@ -24,7 +24,7 @@ var _ = Describe("Seed", func() {
Status: gardencorev1beta1.SeedStatus{
Gardener: &gardencorev1beta1.Gardener{},
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
},
},
@@ -33,7 +33,7 @@ var _ = Describe("Seed", func() {
Status: gardencorev1beta1.SeedStatus{
Gardener: &gardencorev1beta1.Gardener{ID: "thegardener"},
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
},
},
@@ -41,7 +41,7 @@ var _ = Describe("Seed", func() {
Entry("unhealthy available condition (gardenlet ready)", &gardencorev1beta1.Seed{
Status: gardencorev1beta1.SeedStatus{
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionFalse},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionFalse},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
},
},
@@ -49,7 +49,7 @@ var _ = Describe("Seed", func() {
Entry("unhealthy available condition (seed system components healthy)", &gardencorev1beta1.Seed{
Status: gardencorev1beta1.SeedStatus{
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionFalse},
},
},
@@ -59,7 +59,7 @@ var _ = Describe("Seed", func() {
Status: gardencorev1beta1.SeedStatus{
Gardener: &gardencorev1beta1.Gardener{ID: "thegardener"},
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
},
},
@@ -70,7 +70,7 @@ var _ = Describe("Seed", func() {
},
Status: gardencorev1beta1.SeedStatus{
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
},
},
@@ -93,7 +93,7 @@ var _ = Describe("Seed", func() {
Status: gardencorev1beta1.SeedStatus{
Gardener: &gardencorev1beta1.Gardener{Version: "1.12.8"},
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
},
},
@@ -102,7 +102,7 @@ var _ = Describe("Seed", func() {
Status: gardencorev1beta1.SeedStatus{
Gardener: &gardencorev1beta1.Gardener{Version: "1.12.8"},
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
},
},
@@ -111,7 +111,7 @@ var _ = Describe("Seed", func() {
Status: gardencorev1beta1.SeedStatus{
Gardener: &gardencorev1beta1.Gardener{Version: "1.12.8"},
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionFalse},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionFalse},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
},
},
@@ -120,7 +120,7 @@ var _ = Describe("Seed", func() {
Status: gardencorev1beta1.SeedStatus{
Gardener: &gardencorev1beta1.Gardener{Version: "1.12.8"},
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionFalse},
},
},
@@ -129,7 +129,7 @@ var _ = Describe("Seed", func() {
Status: gardencorev1beta1.SeedStatus{
Gardener: &gardencorev1beta1.Gardener{Version: "1.12.8"},
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionFalse},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionFalse},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionFalse},
},
},
diff --git a/plugin/pkg/global/customverbauthorizer/admission.go b/plugin/pkg/global/customverbauthorizer/admission.go
index 13325f63aa2..e488f3b9158 100644
--- a/plugin/pkg/global/customverbauthorizer/admission.go
+++ b/plugin/pkg/global/customverbauthorizer/admission.go
@@ -256,7 +256,7 @@ func (c *CustomVerbAuthorizer) admitShoots(ctx context.Context, a admission.Attr
}
}
- if mustCheckShootAutonomy(oldObj, obj) {
+ if mustCheckIfShootIsSelfHosted(oldObj, obj) {
return c.authorize(ctx, a, CustomVerbShootMarkSelfHosted, "modify .spec.provider.workers[].controlPlane")
}
@@ -421,6 +421,6 @@ func mustCheckLimits(oldLimits, limits *core.Limits, parentCloudProfile *v1beta1
ptr.Deref(limits.MaxNodesTotal, 0) > ptr.Deref(parentCloudProfile.Spec.Limits.MaxNodesTotal, 0)
}
-func mustCheckShootAutonomy(oldShoot, shoot *core.Shoot) bool {
+func mustCheckIfShootIsSelfHosted(oldShoot, shoot *core.Shoot) bool {
return !apiequality.Semantic.DeepEqual(helper.ControlPlaneWorkerPoolForShoot(oldShoot.Spec.Provider.Workers), helper.ControlPlaneWorkerPoolForShoot(shoot.Spec.Provider.Workers))
}
diff --git a/skaffold-gardenadm.yaml b/skaffold-gardenadm.yaml
index 63fecc64b89..c945f0640ed 100644
--- a/skaffold-gardenadm.yaml
+++ b/skaffold-gardenadm.yaml
@@ -889,6 +889,7 @@ build:
- pkg/gardenlet/controller/controllerinstallation/required
- pkg/gardenlet/controller/controllerinstallation/utils
- pkg/gardenlet/controller/gardenlet
+ - pkg/gardenlet/controller/lease
- pkg/gardenlet/controller/managedseed
- pkg/gardenlet/controller/networkpolicy
- pkg/gardenlet/controller/seed
@@ -897,6 +898,7 @@ build:
- pkg/gardenlet/controller/seed/seed
- pkg/gardenlet/controller/shoot
- pkg/gardenlet/controller/shoot/care
+ - pkg/gardenlet/controller/shoot/lease
- pkg/gardenlet/controller/shoot/shoot
- pkg/gardenlet/controller/shoot/shoot/helper
- pkg/gardenlet/controller/shoot/state
diff --git a/skaffold-operator.yaml b/skaffold-operator.yaml
index 234857b7643..4a100372750 100644
--- a/skaffold-operator.yaml
+++ b/skaffold-operator.yaml
@@ -730,6 +730,7 @@ build:
- pkg/controllermanager/controller/credentialsbinding
- pkg/controllermanager/controller/event
- pkg/controllermanager/controller/exposureclass
+ - pkg/controllermanager/controller/gardenletlifecycle
- pkg/controllermanager/controller/managedseedset
- pkg/controllermanager/controller/namespacedcloudprofile
- pkg/controllermanager/controller/project
@@ -741,7 +742,6 @@ build:
- pkg/controllermanager/controller/seed
- pkg/controllermanager/controller/seed/backupbucketscheck
- pkg/controllermanager/controller/seed/extensionscheck
- - pkg/controllermanager/controller/seed/lifecycle
- pkg/controllermanager/controller/seed/reference
- pkg/controllermanager/controller/seed/secrets
- pkg/controllermanager/controller/seed/utils
diff --git a/skaffold-seed.yaml b/skaffold-seed.yaml
index 86d8e27d321..9f60d0474b4 100644
--- a/skaffold-seed.yaml
+++ b/skaffold-seed.yaml
@@ -309,6 +309,7 @@ build:
- pkg/gardenlet/controller/controllerinstallation/required
- pkg/gardenlet/controller/controllerinstallation/utils
- pkg/gardenlet/controller/gardenlet
+ - pkg/gardenlet/controller/lease
- pkg/gardenlet/controller/managedseed
- pkg/gardenlet/controller/networkpolicy
- pkg/gardenlet/controller/seed
@@ -317,6 +318,7 @@ build:
- pkg/gardenlet/controller/seed/seed
- pkg/gardenlet/controller/shoot
- pkg/gardenlet/controller/shoot/care
+ - pkg/gardenlet/controller/shoot/lease
- pkg/gardenlet/controller/shoot/shoot
- pkg/gardenlet/controller/shoot/shoot/helper
- pkg/gardenlet/controller/shoot/state
diff --git a/skaffold.yaml b/skaffold.yaml
index 1d8c51412d5..4ffe908bb22 100644
--- a/skaffold.yaml
+++ b/skaffold.yaml
@@ -305,6 +305,7 @@ build:
- pkg/controllermanager/controller/credentialsbinding
- pkg/controllermanager/controller/event
- pkg/controllermanager/controller/exposureclass
+ - pkg/controllermanager/controller/gardenletlifecycle
- pkg/controllermanager/controller/managedseedset
- pkg/controllermanager/controller/namespacedcloudprofile
- pkg/controllermanager/controller/project
@@ -316,7 +317,6 @@ build:
- pkg/controllermanager/controller/seed
- pkg/controllermanager/controller/seed/backupbucketscheck
- pkg/controllermanager/controller/seed/extensionscheck
- - pkg/controllermanager/controller/seed/lifecycle
- pkg/controllermanager/controller/seed/reference
- pkg/controllermanager/controller/seed/secrets
- pkg/controllermanager/controller/seed/utils
@@ -1225,6 +1225,7 @@ build:
- pkg/gardenlet/controller/controllerinstallation/required
- pkg/gardenlet/controller/controllerinstallation/utils
- pkg/gardenlet/controller/gardenlet
+ - pkg/gardenlet/controller/lease
- pkg/gardenlet/controller/managedseed
- pkg/gardenlet/controller/networkpolicy
- pkg/gardenlet/controller/seed
@@ -1233,6 +1234,7 @@ build:
- pkg/gardenlet/controller/seed/seed
- pkg/gardenlet/controller/shoot
- pkg/gardenlet/controller/shoot/care
+ - pkg/gardenlet/controller/shoot/lease
- pkg/gardenlet/controller/shoot/shoot
- pkg/gardenlet/controller/shoot/shoot/helper
- pkg/gardenlet/controller/shoot/state
diff --git a/test/framework/k8s_utils_test.go b/test/framework/k8s_utils_test.go
index 084a6c5c779..f4e8329f182 100644
--- a/test/framework/k8s_utils_test.go
+++ b/test/framework/k8s_utils_test.go
@@ -317,7 +317,7 @@ func appendShootConditionsToShoot(shoot *gardencorev1beta1.Shoot) {
func appendSeedConditionsToShoot(shoot *gardencorev1beta1.Shoot) {
shoot.Status.Conditions = append(shoot.Status.Conditions, []gardencorev1beta1.Condition{
{
- Type: gardencorev1beta1.SeedGardenletReady,
+ Type: gardencorev1beta1.GardenletReady,
Status: gardencorev1beta1.ConditionTrue,
},
{
diff --git a/test/integration/controllermanager/seed/lifecycle/lifecycle_suite_test.go b/test/integration/controllermanager/gardenletlifecycle/lifecycle_suite_test.go
similarity index 89%
rename from test/integration/controllermanager/seed/lifecycle/lifecycle_suite_test.go
rename to test/integration/controllermanager/gardenletlifecycle/lifecycle_suite_test.go
index f354fbdfde2..6dd036d0ad6 100644
--- a/test/integration/controllermanager/seed/lifecycle/lifecycle_suite_test.go
+++ b/test/integration/controllermanager/gardenletlifecycle/lifecycle_suite_test.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
-package lifecycle_test
+package gardenletlifecycle_test
import (
"context"
@@ -15,7 +15,6 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
- "k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/client-go/rest"
testclock "k8s.io/utils/clock/testing"
"k8s.io/utils/ptr"
@@ -30,15 +29,15 @@ import (
"github.com/gardener/gardener/pkg/api/indexer"
"github.com/gardener/gardener/pkg/client/kubernetes"
controllermanagerconfigv1alpha1 "github.com/gardener/gardener/pkg/controllermanager/apis/config/v1alpha1"
- "github.com/gardener/gardener/pkg/controllermanager/controller/seed/lifecycle"
+ "github.com/gardener/gardener/pkg/controllermanager/controller/gardenletlifecycle"
"github.com/gardener/gardener/pkg/logger"
- "github.com/gardener/gardener/pkg/utils"
+ . "github.com/gardener/gardener/pkg/utils/test/matchers"
gardenerenvtest "github.com/gardener/gardener/test/envtest"
)
-func TestLifecycle(t *testing.T) {
+func TestGardenletLifecycle(t *testing.T) {
RegisterFailHandler(Fail)
- RunSpecs(t, "Test Integration ControllerManager Seed Lifecycle Suite")
+ RunSpecs(t, "Test Integration ControllerManager GardenletLifecycle Suite")
}
const (
@@ -90,13 +89,17 @@ var _ = BeforeSuite(func() {
By("Create test Namespace")
testNamespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
- // create dedicated namespace for each test run, so that we can run multiple tests concurrently for stress tests
- GenerateName: testID + "-",
+ GenerateName: "gardener-system-seed-lease-",
},
}
Expect(testClient.Create(ctx, testNamespace)).To(Succeed())
log.Info("Created Namespace for test", "namespaceName", testNamespace.Name)
- testRunID = testNamespace.Name + "-" + utils.ComputeSHA256Hex([]byte(uuid.NewUUID()))[:8]
+ testRunID = testNamespace.Name
+
+ DeferCleanup(func() {
+ By("Delete test Namespace")
+ Expect(testClient.Delete(ctx, testNamespace)).To(Or(Succeed(), BeNotFoundError()))
+ })
By("Setup manager")
mgr, err := manager.New(restConfig, manager.Options{
@@ -117,7 +120,7 @@ var _ = BeforeSuite(func() {
By("Register controller")
fakeClock = testclock.NewFakeClock(time.Now())
- Expect((&lifecycle.Reconciler{
+ Expect((&gardenletlifecycle.Reconciler{
Config: controllermanagerconfigv1alpha1.SeedControllerConfiguration{
MonitorPeriod: &metav1.Duration{Duration: seedMonitorPeriod},
ShootMonitorPeriod: &metav1.Duration{Duration: shootMonitorPeriod},
diff --git a/test/integration/controllermanager/seed/lifecycle/lifecycle_test.go b/test/integration/controllermanager/gardenletlifecycle/lifecycle_test.go
similarity index 98%
rename from test/integration/controllermanager/seed/lifecycle/lifecycle_test.go
rename to test/integration/controllermanager/gardenletlifecycle/lifecycle_test.go
index f180c398e23..2dc7b45d7a2 100644
--- a/test/integration/controllermanager/seed/lifecycle/lifecycle_test.go
+++ b/test/integration/controllermanager/gardenletlifecycle/lifecycle_test.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
-package lifecycle_test
+package gardenletlifecycle_test
import (
"time"
@@ -20,7 +20,7 @@ import (
. "github.com/gardener/gardener/pkg/utils/test/matchers"
)
-var _ = Describe("Seed Lifecycle controller tests", func() {
+var _ = Describe("Gardenlet Lifecycle controller tests", func() {
var (
seed *gardencorev1beta1.Seed
lease *coordinationv1.Lease
@@ -168,7 +168,7 @@ var _ = Describe("Seed Lifecycle controller tests", func() {
By("Add GardenletReady condition to Seed")
patch := client.MergeFrom(seed.DeepCopy())
seed.Status.Conditions = []gardencorev1beta1.Condition{{
- Type: gardencorev1beta1.SeedGardenletReady,
+ Type: gardencorev1beta1.GardenletReady,
Status: gardencorev1beta1.ConditionTrue,
LastTransitionTime: metav1.Time{Time: fakeClock.Now().Add(-24 * time.Hour)},
}}
diff --git a/test/integration/controllermanager/managedseedset/managedseedset_test.go b/test/integration/controllermanager/managedseedset/managedseedset_test.go
index a8faa98289b..87a9d9ce1a1 100644
--- a/test/integration/controllermanager/managedseedset/managedseedset_test.go
+++ b/test/integration/controllermanager/managedseedset/managedseedset_test.go
@@ -90,7 +90,7 @@ var _ = Describe("ManagedSeedSet controller test", func() {
seed.Status = gardencorev1beta1.SeedStatus{
ObservedGeneration: seed.GetGeneration(),
Conditions: []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedBackupBucketsReady, Status: gardencorev1beta1.ConditionTrue},
},
diff --git a/test/integration/controllermanager/shoot/conditions/conditions_test.go b/test/integration/controllermanager/shoot/conditions/conditions_test.go
index 3db3e58aeed..f82bd180e54 100644
--- a/test/integration/controllermanager/shoot/conditions/conditions_test.go
+++ b/test/integration/controllermanager/shoot/conditions/conditions_test.go
@@ -130,7 +130,7 @@ var _ = Describe("Shoot Conditions controller tests", func() {
}).Should(And(
Not(ContainCondition(OfType(gardencorev1beta1.SeedBackupBucketsReady))),
Not(ContainCondition(OfType(gardencorev1beta1.SeedExtensionsReady))),
- Not(ContainCondition(OfType(gardencorev1beta1.SeedGardenletReady))),
+ Not(ContainCondition(OfType(gardencorev1beta1.GardenletReady))),
Not(ContainCondition(OfType(gardencorev1beta1.SeedSystemComponentsHealthy))),
))
})
@@ -150,7 +150,7 @@ var _ = Describe("Shoot Conditions controller tests", func() {
}).Should(And(
Not(ContainCondition(OfType(gardencorev1beta1.SeedBackupBucketsReady))),
Not(ContainCondition(OfType(gardencorev1beta1.SeedExtensionsReady))),
- Not(ContainCondition(OfType(gardencorev1beta1.SeedGardenletReady))),
+ Not(ContainCondition(OfType(gardencorev1beta1.GardenletReady))),
Not(ContainCondition(OfType(gardencorev1beta1.SeedSystemComponentsHealthy))),
))
})
@@ -182,7 +182,7 @@ var _ = Describe("Shoot Conditions controller tests", func() {
conditions := []gardencorev1beta1.Condition{
{Type: gardencorev1beta1.SeedBackupBucketsReady, Status: gardencorev1beta1.ConditionProgressing},
{Type: gardencorev1beta1.SeedExtensionsReady, Status: gardencorev1beta1.ConditionProgressing},
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionProgressing},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionProgressing},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionProgressing},
{Type: gardencorev1beta1.ConditionType("custom"), Status: gardencorev1beta1.ConditionProgressing},
}
@@ -199,7 +199,7 @@ var _ = Describe("Shoot Conditions controller tests", func() {
}).Should(And(
ContainCondition(OfType(gardencorev1beta1.SeedBackupBucketsReady)),
ContainCondition(OfType(gardencorev1beta1.SeedExtensionsReady)),
- ContainCondition(OfType(gardencorev1beta1.SeedGardenletReady)),
+ ContainCondition(OfType(gardencorev1beta1.GardenletReady)),
ContainCondition(OfType(gardencorev1beta1.SeedSystemComponentsHealthy)),
ContainCondition(OfType("custom")),
))
@@ -211,7 +211,7 @@ var _ = Describe("Shoot Conditions controller tests", func() {
}).Should(And(
ContainCondition(OfType(gardencorev1beta1.SeedBackupBucketsReady)),
ContainCondition(OfType(gardencorev1beta1.SeedExtensionsReady)),
- ContainCondition(OfType(gardencorev1beta1.SeedGardenletReady)),
+ ContainCondition(OfType(gardencorev1beta1.GardenletReady)),
ContainCondition(OfType(gardencorev1beta1.SeedSystemComponentsHealthy)),
ContainCondition(OfType("custom")),
))
@@ -235,7 +235,7 @@ var _ = Describe("Shoot Conditions controller tests", func() {
}).ShouldNot(And(
ContainCondition(OfType(gardencorev1beta1.SeedBackupBucketsReady)),
ContainCondition(OfType(gardencorev1beta1.SeedExtensionsReady)),
- ContainCondition(OfType(gardencorev1beta1.SeedGardenletReady)),
+ ContainCondition(OfType(gardencorev1beta1.GardenletReady)),
ContainCondition(OfType(gardencorev1beta1.SeedSystemComponentsHealthy)),
ContainCondition(OfType("custom")),
))
diff --git a/test/integration/controllermanager/shoot/migration/migration_test.go b/test/integration/controllermanager/shoot/migration/migration_test.go
index 8323a77e4e0..316126be7c9 100644
--- a/test/integration/controllermanager/shoot/migration/migration_test.go
+++ b/test/integration/controllermanager/shoot/migration/migration_test.go
@@ -240,7 +240,7 @@ var _ = Describe("Shoot Migration controller tests", Ordered, func() {
destinationSeed.Status.Gardener = sourceSeed.Status.Gardener
destinationSeed.Status.ObservedGeneration = destinationSeed.Generation
destinationSeed.Status.Conditions = []gardencorev1beta1.Condition{
- {Type: gardencorev1beta1.SeedGardenletReady, Status: gardencorev1beta1.ConditionTrue},
+ {Type: gardencorev1beta1.GardenletReady, Status: gardencorev1beta1.ConditionTrue},
{Type: gardencorev1beta1.SeedSystemComponentsHealthy, Status: gardencorev1beta1.ConditionTrue},
}
Expect(testClient.Status().Update(ctx, destinationSeed)).To(Succeed())
diff --git a/test/integration/gardenlet/seed/lease/lease_suite_test.go b/test/integration/gardenlet/seed/lease/lease_suite_test.go
index 1689ccb7cb4..b2f4c2159c8 100644
--- a/test/integration/gardenlet/seed/lease/lease_suite_test.go
+++ b/test/integration/gardenlet/seed/lease/lease_suite_test.go
@@ -172,16 +172,9 @@ var _ = BeforeSuite(func() {
fakeClock = testclock.NewFakeClock(time.Now())
healthManager = healthz.NewDefaultHealthz()
- Expect((&lease.Reconciler{
- SeedRESTClient: kubernetesClient.RESTClient(),
- Config: gardenletconfigv1alpha1.SeedControllerConfiguration{
- LeaseResyncSeconds: ptr.To[int32](1),
- },
- Clock: fakeClock,
- HealthManager: healthManager,
- LeaseNamespace: testNamespace.Name,
- SeedName: seed.Name,
- }).AddToManager(mgr, mgr)).To(Succeed())
+ Expect(lease.AddToManager(mgr, mgr, kubernetesClient.RESTClient(), gardenletconfigv1alpha1.SeedControllerConfiguration{
+ LeaseResyncSeconds: ptr.To[int32](1),
+ }, healthManager, seed.Name, fakeClock, &testNamespace.Name)).To(Succeed())
By("Start manager")
mgrContext, mgrCancel := context.WithCancel(ctx)
diff --git a/test/integration/gardenlet/seed/lease/lease_test.go b/test/integration/gardenlet/seed/lease/lease_test.go
index dc5bc9d4482..b7a35e1c922 100644
--- a/test/integration/gardenlet/seed/lease/lease_test.go
+++ b/test/integration/gardenlet/seed/lease/lease_test.go
@@ -18,7 +18,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
- leasereconciler "github.com/gardener/gardener/pkg/gardenlet/controller/seed/lease"
+ leasecontroller "github.com/gardener/gardener/pkg/gardenlet/controller/lease"
"github.com/gardener/gardener/pkg/utils/test"
. "github.com/gardener/gardener/pkg/utils/test/matchers"
)
@@ -26,85 +26,99 @@ import (
var _ = Describe("Seed lease controller tests", func() {
var lease *coordinationv1.Lease
- BeforeEach(func() {
+ BeforeEach(OncePerOrdered, func() {
fakeClock.SetTime(time.Now())
lease = &coordinationv1.Lease{ObjectMeta: metav1.ObjectMeta{Name: seed.Name, Namespace: testNamespace.Name}}
})
- It("should maintain the Lease object and set the internal health status to true", func() {
- By("Ensure Lease got maintained")
- Eventually(func(g Gomega) {
- g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
- g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Seed", Name: seed.Name, UID: seed.UID}))
- g.Expect(lease.Spec.RenewTime.Sub(fakeClock.Now())).To(BeNumerically("<=", 0))
- g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(1))))
- g.Expect(lease.Spec.HolderIdentity).To(Equal(&seed.Name))
- g.Expect(healthManager.Get()).To(BeTrue())
- }).Should(Succeed())
-
- By("Ensure GardenletReady condition was maintained")
- Eventually(func(g Gomega) {
- g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(seed), seed)).To(Succeed())
- g.Expect(seed.Status.Conditions).To(ContainCondition(OfType(gardencorev1beta1.SeedGardenletReady), WithStatus(gardencorev1beta1.ConditionTrue)))
- }).Should(Succeed())
-
- By("Step clock")
- fakeClock.Step(time.Hour)
-
- By("Ensure health status is true")
- Consistently(func() bool {
- return healthManager.Get()
- }).Should(BeTrue())
-
- By("Ensure Lease got updated")
- Eventually(func(g Gomega) {
- g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
- g.Expect(lease.Spec.RenewTime.Sub(fakeClock.Now())).To(BeNumerically("<=", 0))
- g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Seed", Name: seed.Name, UID: seed.UID}))
- g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(1))))
- g.Expect(lease.Spec.HolderIdentity).To(Equal(&seed.Name))
- }).Should(Succeed())
+ Describe("maintain the Lease object and set the internal health status to true", Ordered, func() {
+ It("should ensured Lease gets maintained", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
+ g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Seed", Name: seed.Name, UID: seed.UID}))
+ g.Expect(lease.Spec.RenewTime.Sub(fakeClock.Now())).To(BeNumerically("<=", 0))
+ g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(1))))
+ g.Expect(lease.Spec.HolderIdentity).To(Equal(&seed.Name))
+ g.Expect(healthManager.Get()).To(BeTrue())
+ }).Should(Succeed())
+ })
+
+ It("should ensure GardenletReady condition gets maintained", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(seed), seed)).To(Succeed())
+ g.Expect(seed.Status.Conditions).To(ContainCondition(OfType(gardencorev1beta1.GardenletReady), WithStatus(gardencorev1beta1.ConditionTrue)))
+ }).Should(Succeed())
+ })
+
+ It("should step the fake clock", func() {
+ fakeClock.Step(time.Hour)
+ })
+
+ It("should ensure health status is set to true", func() {
+ Consistently(func() bool {
+ return healthManager.Get()
+ }).Should(BeTrue())
+ })
+
+ It("should ensure Lease gets updated", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
+ g.Expect(lease.Spec.RenewTime.Sub(fakeClock.Now())).To(BeNumerically("<=", 0))
+ g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Seed", Name: seed.Name, UID: seed.UID}))
+ g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(1))))
+ g.Expect(lease.Spec.HolderIdentity).To(Equal(&seed.Name))
+ }).Should(Succeed())
+ })
})
- It("should not update the Lease object and set the internal health status to false", func() {
+ Describe("do not update the Lease object and set the internal health status to false", Ordered, func() {
var fakeError error
- DeferCleanup(test.WithVar(&leasereconciler.CheckSeedConnection, func(context.Context, rest.Interface) error { return fakeError }))
-
- By("Ensure Lease got maintained")
- Eventually(func(g Gomega) {
- g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
- g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Seed", Name: seed.Name, UID: seed.UID}))
- g.Expect(lease.Spec.RenewTime.Sub(fakeClock.Now())).To(BeNumerically("<=", 0))
- g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(1))))
- g.Expect(lease.Spec.HolderIdentity).To(Equal(&seed.Name))
- g.Expect(healthManager.Get()).To(BeTrue())
- }).Should(Succeed())
-
- By("Ensure GardenletReady condition was maintained")
- Eventually(func(g Gomega) {
- g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(seed), seed)).To(Succeed())
- g.Expect(seed.Status.Conditions).To(ContainCondition(OfType(gardencorev1beta1.SeedGardenletReady), WithStatus(gardencorev1beta1.ConditionTrue)))
- }).Should(Succeed())
-
- By("Ensure seed connection fails")
- fakeError = errors.New("fake")
-
- By("Ensure health status was set to false")
- Eventually(func() bool {
- return healthManager.Get()
- }).Should(BeFalse())
-
- By("Step clock")
- fakeClock.Step(time.Hour)
-
- By("Ensure Lease did not get updated")
- Consistently(func(g Gomega) {
- g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
- g.Expect(fakeClock.Now().Sub(lease.Spec.RenewTime.Time)).To(BeNumerically(">=", time.Hour))
- g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Seed", Name: seed.Name, UID: seed.UID}))
- g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(1))))
- g.Expect(lease.Spec.HolderIdentity).To(Equal(&seed.Name))
- }).Should(Succeed())
+
+ BeforeEach(OncePerOrdered, func() {
+ DeferCleanup(test.WithVar(&leasecontroller.CheckConnection, func(context.Context, rest.Interface) error { return fakeError }))
+ })
+
+ It("should ensure Lease gets maintained", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
+ g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Seed", Name: seed.Name, UID: seed.UID}))
+ g.Expect(lease.Spec.RenewTime.Sub(fakeClock.Now())).To(BeNumerically("<=", 0))
+ g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(1))))
+ g.Expect(lease.Spec.HolderIdentity).To(Equal(&seed.Name))
+ g.Expect(healthManager.Get()).To(BeTrue())
+ }).Should(Succeed())
+ })
+
+ It("should ensure GardenletReady condition gets maintained", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(seed), seed)).To(Succeed())
+ g.Expect(seed.Status.Conditions).To(ContainCondition(OfType(gardencorev1beta1.GardenletReady), WithStatus(gardencorev1beta1.ConditionTrue)))
+ }).Should(Succeed())
+ })
+
+ It("should make the seed connection fail", func() {
+ fakeError = errors.New("fake")
+ })
+
+ It("should ensure health status gets set to false", func() {
+ Eventually(func() bool {
+ return healthManager.Get()
+ }).Should(BeFalse())
+ })
+
+ It("should step the fake clock", func() {
+ fakeClock.Step(time.Hour)
+ })
+
+ It("should ensure the Lease object is not updated and the internal health status remains false", func() {
+ Consistently(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
+ g.Expect(fakeClock.Now().Sub(lease.Spec.RenewTime.Time)).To(BeNumerically(">=", time.Hour))
+ g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Seed", Name: seed.Name, UID: seed.UID}))
+ g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(1))))
+ g.Expect(lease.Spec.HolderIdentity).To(Equal(&seed.Name))
+ }).Should(Succeed())
+ })
})
})
diff --git a/test/integration/gardenlet/shoot/lease/lease_suite_test.go b/test/integration/gardenlet/shoot/lease/lease_suite_test.go
new file mode 100644
index 00000000000..cf1843c6191
--- /dev/null
+++ b/test/integration/gardenlet/shoot/lease/lease_suite_test.go
@@ -0,0 +1,187 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package lease_test
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "github.com/go-logr/logr"
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ corev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ kubernetesclientset "k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/rest"
+ testclock "k8s.io/utils/clock/testing"
+ "k8s.io/utils/ptr"
+ "sigs.k8s.io/controller-runtime/pkg/cache"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ controllerconfig "sigs.k8s.io/controller-runtime/pkg/config"
+ "sigs.k8s.io/controller-runtime/pkg/envtest"
+ logf "sigs.k8s.io/controller-runtime/pkg/log"
+ "sigs.k8s.io/controller-runtime/pkg/log/zap"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+ metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
+
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
+ "github.com/gardener/gardener/pkg/client/kubernetes"
+ "github.com/gardener/gardener/pkg/gardenlet/controller/shoot/lease"
+ "github.com/gardener/gardener/pkg/healthz"
+ "github.com/gardener/gardener/pkg/logger"
+ . "github.com/gardener/gardener/pkg/utils/test/matchers"
+ gardenerenvtest "github.com/gardener/gardener/test/envtest"
+)
+
+func TestLease(t *testing.T) {
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Test Integration Gardenlet Shoot Lease Suite")
+}
+
+const testID = "shoot-lease-controller-test"
+
+var (
+ ctx = context.Background()
+ log logr.Logger
+
+ restConfig *rest.Config
+ testEnv *gardenerenvtest.GardenerTestEnvironment
+ testClient client.Client
+
+ testNamespace *corev1.Namespace
+ testRunID string
+
+ shoot *gardencorev1beta1.Shoot
+ fakeClock *testclock.FakeClock
+ healthManager healthz.Manager
+)
+
+var _ = BeforeSuite(func() {
+ logf.SetLogger(logger.MustNewZapLogger(logger.DebugLevel, logger.FormatJSON, zap.WriteTo(GinkgoWriter)))
+ log = logf.Log.WithName(testID)
+
+ By("Start test environment")
+ testEnv = &gardenerenvtest.GardenerTestEnvironment{
+ Environment: &envtest.Environment{},
+ GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{
+ Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ShootMutator"},
+ },
+ }
+
+ var err error
+ restConfig, err = testEnv.Start()
+ Expect(err).NotTo(HaveOccurred())
+ Expect(restConfig).NotTo(BeNil())
+
+ DeferCleanup(func() {
+ By("Stop test environment")
+ Expect(testEnv.Stop()).To(Succeed())
+ })
+
+ testSchemeBuilder := runtime.NewSchemeBuilder(
+ kubernetes.AddGardenSchemeToScheme,
+ resourcesv1alpha1.AddToScheme,
+ )
+ testScheme := runtime.NewScheme()
+ Expect(testSchemeBuilder.AddToScheme(testScheme)).To(Succeed())
+
+ By("Create test client")
+ testClient, err = client.New(restConfig, client.Options{Scheme: testScheme})
+ Expect(err).NotTo(HaveOccurred())
+
+ By("Create test Namespace")
+ testNamespace = &corev1.Namespace{
+ ObjectMeta: metav1.ObjectMeta{
+ GenerateName: "garden-",
+ },
+ }
+ Expect(testClient.Create(ctx, testNamespace)).To(Succeed())
+ log.Info("Created Namespace for test", "namespaceName", testNamespace.Name)
+ testRunID = testNamespace.Name
+
+ DeferCleanup(func() {
+ By("Delete test Namespace")
+ Expect(testClient.Delete(ctx, testNamespace)).To(Or(Succeed(), BeNotFoundError()))
+ })
+
+ By("Create Shoot")
+ shoot = &gardencorev1beta1.Shoot{
+ ObjectMeta: metav1.ObjectMeta{
+ GenerateName: "shoot-",
+ Namespace: testNamespace.Name,
+ Labels: map[string]string{testID: testRunID},
+ },
+ Spec: gardencorev1beta1.ShootSpec{
+ CredentialsBindingName: ptr.To("my-provider-account"),
+ CloudProfile: &gardencorev1beta1.CloudProfileReference{Name: "test-cloudprofile", Kind: "CloudProfile"},
+ Region: "foo-region",
+ Provider: gardencorev1beta1.Provider{
+ Type: "test",
+ Workers: []gardencorev1beta1.Worker{
+ {
+ Name: "cpu-worker",
+ Minimum: 2,
+ Maximum: 2,
+ Machine: gardencorev1beta1.Machine{
+ Type: "large",
+ },
+ },
+ },
+ },
+ Kubernetes: gardencorev1beta1.Kubernetes{
+ Version: "1.31.1",
+ },
+ Networking: &gardencorev1beta1.Networking{
+ Type: ptr.To("foo-networking"),
+ },
+ },
+ }
+ Expect(testClient.Create(ctx, shoot)).To(Succeed())
+ log.Info("Created Shoot for test", "shoot", client.ObjectKeyFromObject(shoot))
+
+ DeferCleanup(func() {
+ By("Delete Shoot")
+ Expect(testClient.Delete(ctx, shoot)).To(Or(Succeed(), BeNotFoundError()))
+ })
+
+ By("Setup manager")
+ mgr, err := manager.New(restConfig, manager.Options{
+ Scheme: testScheme,
+ Metrics: metricsserver.Options{BindAddress: "0"},
+ Cache: cache.Options{
+ DefaultNamespaces: map[string]cache.Config{testNamespace.Name: {}},
+ },
+ Controller: controllerconfig.Controller{
+ SkipNameValidation: ptr.To(true),
+ },
+ })
+ Expect(err).NotTo(HaveOccurred())
+
+ By("Create Kubernetes clientset")
+ kubernetesClient, err := kubernetesclientset.NewForConfig(mgr.GetConfig())
+ Expect(err).NotTo(HaveOccurred())
+
+ By("Register controller")
+ fakeClock = testclock.NewFakeClock(time.Now())
+ healthManager = healthz.NewDefaultHealthz()
+
+ Expect(lease.AddToManager(mgr, mgr, kubernetesClient.RESTClient(), healthManager, fakeClock)).To(Succeed())
+
+ By("Start manager")
+ mgrContext, mgrCancel := context.WithCancel(ctx)
+
+ go func() {
+ defer GinkgoRecover()
+ Expect(mgr.Start(mgrContext)).To(Succeed())
+ }()
+
+ DeferCleanup(func() {
+ By("Stop manager")
+ mgrCancel()
+ })
+})
diff --git a/test/integration/gardenlet/shoot/lease/lease_test.go b/test/integration/gardenlet/shoot/lease/lease_test.go
new file mode 100644
index 00000000000..fcaa7f22192
--- /dev/null
+++ b/test/integration/gardenlet/shoot/lease/lease_test.go
@@ -0,0 +1,124 @@
+// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package lease_test
+
+import (
+ "context"
+ "errors"
+ "time"
+
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gstruct"
+ coordinationv1 "k8s.io/api/coordination/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/rest"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+
+ gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
+ leasecontroller "github.com/gardener/gardener/pkg/gardenlet/controller/lease"
+ "github.com/gardener/gardener/pkg/utils/test"
+ . "github.com/gardener/gardener/pkg/utils/test/matchers"
+)
+
+var _ = Describe("Shoot lease controller tests", func() {
+ var lease *coordinationv1.Lease
+
+ BeforeEach(OncePerOrdered, func() {
+ fakeClock.SetTime(time.Now())
+
+ lease = &coordinationv1.Lease{ObjectMeta: metav1.ObjectMeta{Name: "self-hosted-shoot-" + shoot.Name, Namespace: shoot.Namespace}}
+ })
+
+ Describe("maintain the Lease object and set the internal health status to true", Ordered, func() {
+ It("should ensured Lease gets maintained", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
+ g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Shoot", Name: shoot.Name, UID: shoot.UID}))
+ g.Expect(lease.Spec.RenewTime.Sub(fakeClock.Now())).To(BeNumerically("<=", 0))
+ g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(2))))
+ g.Expect(lease.Spec.HolderIdentity).To(Equal(&shoot.Name))
+ g.Expect(healthManager.Get()).To(BeTrue())
+ }).Should(Succeed())
+ })
+
+ It("should ensure GardenletReady condition gets maintained", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(shoot), shoot)).To(Succeed())
+ g.Expect(shoot.Status.Conditions).To(ContainCondition(OfType(gardencorev1beta1.GardenletReady), WithStatus(gardencorev1beta1.ConditionTrue)))
+ }).Should(Succeed())
+ })
+
+ It("should step the fake clock", func() {
+ fakeClock.Step(time.Hour)
+ })
+
+ It("should ensure health status is set to true", func() {
+ Consistently(func() bool {
+ return healthManager.Get()
+ }).Should(BeTrue())
+ })
+
+ It("should ensure Lease gets updated", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
+ g.Expect(lease.Spec.RenewTime.Sub(fakeClock.Now())).To(BeNumerically("<=", 0))
+ g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Shoot", Name: shoot.Name, UID: shoot.UID}))
+ g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(2))))
+ g.Expect(lease.Spec.HolderIdentity).To(Equal(&shoot.Name))
+ }).Should(Succeed())
+ })
+ })
+
+ Describe("do not update the Lease object and set the internal health status to false", Ordered, func() {
+ var fakeError error
+
+ BeforeEach(OncePerOrdered, func() {
+ DeferCleanup(test.WithVar(&leasecontroller.CheckConnection, func(context.Context, rest.Interface) error { return fakeError }))
+ })
+
+ It("should ensure Lease gets maintained", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
+ g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Shoot", Name: shoot.Name, UID: shoot.UID}))
+ g.Expect(lease.Spec.RenewTime.Sub(fakeClock.Now())).To(BeNumerically("<=", 0))
+ g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(2))))
+ g.Expect(lease.Spec.HolderIdentity).To(Equal(&shoot.Name))
+ g.Expect(healthManager.Get()).To(BeTrue())
+ }).Should(Succeed())
+ })
+
+ It("should ensure GardenletReady condition gets maintained", func() {
+ Eventually(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(shoot), shoot)).To(Succeed())
+ g.Expect(shoot.Status.Conditions).To(ContainCondition(OfType(gardencorev1beta1.GardenletReady), WithStatus(gardencorev1beta1.ConditionTrue)))
+ }).Should(Succeed())
+ })
+
+ It("should make the seed connection fail", func() {
+ fakeError = errors.New("fake")
+ })
+
+ It("should ensure health status gets set to false", func() {
+ Eventually(func() bool {
+ return healthManager.Get()
+ }).Should(BeFalse())
+ })
+
+ It("should step the fake clock", func() {
+ fakeClock.Step(time.Hour)
+ })
+
+ It("should ensure the Lease object is not updated and the internal health status remains false", func() {
+ Consistently(func(g Gomega) {
+ g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(lease), lease)).To(Succeed())
+ g.Expect(fakeClock.Now().Sub(lease.Spec.RenewTime.Time)).To(BeNumerically(">=", time.Hour))
+ g.Expect(lease.OwnerReferences).To(ConsistOf(metav1.OwnerReference{APIVersion: "core.gardener.cloud/v1beta1", Kind: "Shoot", Name: shoot.Name, UID: shoot.UID}))
+ g.Expect(lease.Spec.LeaseDurationSeconds).To(PointTo(Equal(int32(2))))
+ g.Expect(lease.Spec.HolderIdentity).To(Equal(&shoot.Name))
+ }).Should(Succeed())
+ })
+ })
+})
diff --git a/test/integration/scheduler/shoot/shoot_test.go b/test/integration/scheduler/shoot/shoot_test.go
index 6882e283802..c4525344f24 100644
--- a/test/integration/scheduler/shoot/shoot_test.go
+++ b/test/integration/scheduler/shoot/shoot_test.go
@@ -731,7 +731,7 @@ func createSeed(region string, zones []string, accessRestrictions []gardencorev1
},
Conditions: []gardencorev1beta1.Condition{
{
- Type: gardencorev1beta1.SeedGardenletReady,
+ Type: gardencorev1beta1.GardenletReady,
Status: gardencorev1beta1.ConditionTrue,
},
},
From 58c114918a31aa99be01e257f9fec838204b3930 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Tue, 11 Nov 2025 10:43:50 +0100
Subject: [PATCH 078/176] Update helm to v3.19.1 (#13408)
---
go.mod | 2 +-
go.sum | 4 ++--
hack/tools.mk | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/go.mod b/go.mod
index 81f96642331..56392687794 100644
--- a/go.mod
+++ b/go.mod
@@ -60,7 +60,7 @@ require (
gomodules.xyz/jsonpatch/v2 v2.5.0
gonum.org/v1/gonum v0.16.0
google.golang.org/protobuf v1.36.10
- helm.sh/helm/v3 v3.18.6
+ helm.sh/helm/v3 v3.19.1
istio.io/api v1.27.3
istio.io/client-go v1.27.2
k8s.io/api v0.34.1
diff --git a/go.sum b/go.sum
index 723004333db..f119bd3bc96 100644
--- a/go.sum
+++ b/go.sum
@@ -1074,8 +1074,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
-helm.sh/helm/v3 v3.18.6 h1:S/2CqcYnNfLckkHLI0VgQbxgcDaU3N4A/46E3n9wSNY=
-helm.sh/helm/v3 v3.18.6/go.mod h1:L/dXDR2r539oPlFP1PJqKAC1CUgqHJDLkxKpDGrWnyg=
+helm.sh/helm/v3 v3.19.1 h1:QVMzHbanyurO8oynx0drDOfG02XxSvrHqaFrf9yrMf0=
+helm.sh/helm/v3 v3.19.1/go.mod h1:gX10tB5ErM+8fr7bglUUS/UfTOO8UUTYWIBH1IYNnpE=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/hack/tools.mk b/hack/tools.mk
index 2217843c385..02dd2c23ab7 100644
--- a/hack/tools.mk
+++ b/hack/tools.mk
@@ -65,7 +65,7 @@ GO_ADD_LICENSE_VERSION ?= v1.2.0
GOIMPORTSREVISER_VERSION ?= v3.10.0
GO_VULN_CHECK_VERSION ?= latest
# renovate: datasource=github-releases depName=helm/helm
-HELM_VERSION ?= v3.18.6
+HELM_VERSION ?= v3.19.1
# renovate: datasource=github-releases depName=kubernetes-sigs/kind
KIND_VERSION ?= v0.30.0
# renovate: datasource=github-releases depName=kubernetes/kubernetes
From 1ba4d935ed202b5da4cd9d4ad91f9e58b540ab2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Oliver=20G=C3=B6tz?=
<47362717+oliver-goetz@users.noreply.github.com>
Date: Tue, 11 Nov 2025 15:02:51 +0100
Subject: [PATCH 079/176] Fix local setup for docker>=v29.0.0 (#13410)
---
hack/kind-up.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hack/kind-up.sh b/hack/kind-up.sh
index 2d8b9875c1c..4493b0604b2 100755
--- a/hack/kind-up.sh
+++ b/hack/kind-up.sh
@@ -84,7 +84,7 @@ setup_kind_network() {
local network network_options network_ipam expected_network_ipam
network="$(docker network inspect $existing_network_id | yq '.[]')"
network_options="$(echo "$network" | yq '.EnableIPv6 + "," + .Options["com.docker.network.bridge.enable_ip_masquerade"]')"
- network_ipam="$(echo "$network" | yq '.IPAM.Config' -o=json -I=0)"
+ network_ipam="$(echo "$network" | yq '.IPAM.Config' -o=json -I=0 | sed -E 's/"IPRange":"",//g')"
expected_network_ipam='[{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"},{"Subnet":"fd00:10::/64","Gateway":"fd00:10::1"}]'
if [ "$network_options" = 'true,true' ] && [ "$network_ipam" = "$expected_network_ipam" ] ; then
From 448264134c7e93a2a949626fe975299d0bba8eda Mon Sep 17 00:00:00 2001
From: Tomas Valasek <13797085+tvalasek@users.noreply.github.com>
Date: Tue, 11 Nov 2025 16:07:53 +0100
Subject: [PATCH 080/176] Flux link fix (#13418)
The original repository was archived by the owner on Apr 11, 2025.
This is the new link
---
extensions/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extensions/README.md b/extensions/README.md
index bc2986fbf96..9ff935d5505 100644
--- a/extensions/README.md
+++ b/extensions/README.md
@@ -65,7 +65,7 @@ The primary DNS provider manages `DNSRecord` resources (mandatory for Gardener r
- [Shoot Certificate Service](https://github.com/gardener/gardener-extension-shoot-cert-service)
- [Shoot DNS Service](https://github.com/gardener/gardener-extension-shoot-dns-service)
- [Shoot Falco Service](https://github.com/gardener/gardener-extension-shoot-falco-service)
-- [Shoot Flux Service](https://github.com/23technologies/gardener-extension-shoot-flux)
+- [Shoot Flux Service](https://github.com/stackitcloud/gardener-extension-shoot-flux)
- [Shoot Lakom Service](https://github.com/gardener/gardener-extension-shoot-lakom-service)
- [Shoot Networking Filter](https://github.com/gardener/gardener-extension-shoot-networking-filter)
- [Shoot Networking Problem Detector](https://github.com/gardener/gardener-extension-shoot-networking-problemdetector)
From a9c146a86ba2901604daad81c4e1479721d1b8ca Mon Sep 17 00:00:00 2001
From: Indrit Fejza
Date: Tue, 11 Nov 2025 19:05:52 +0100
Subject: [PATCH 081/176] Add VPN note to getting started locally guide
(#13334)
* Add VPN note to getting started locally guide
Added a note about VPN issues affecting kubeconfig setup.
* improve wording
* improve help message
* Update docs/deployment/getting_started_locally.md
Co-authored-by: Marc Vornetran
---------
Co-authored-by: Marc Vornetran
---
docs/deployment/getting_started_locally.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/docs/deployment/getting_started_locally.md b/docs/deployment/getting_started_locally.md
index 82a1712b588..764b54978fa 100644
--- a/docs/deployment/getting_started_locally.md
+++ b/docs/deployment/getting_started_locally.md
@@ -329,6 +329,10 @@ For convenience a [helper script](../../hack/usage/generate-admin-kubeconf.sh) i
./hack/usage/generate-admin-kubeconf.sh > admin-kubeconf.yaml
```
+> [!NOTE]
+> Keep in mind that using a VPN on your local machine could cause problems with the setup, and the shoot's kubeconfig could fail with connection issues.
+> If you experience connection problems using the shoot's kubeconfig, try disabling the VPN first.
+
If you want to change the default namespace or shoot name, you can do so by passing different values as arguments.
```bash
From 0405e73d2de53a08fa2ae337dd91c903f17e0307 Mon Sep 17 00:00:00 2001
From: Dominik Froehlich
Date: Tue, 11 Nov 2025 19:05:58 +0100
Subject: [PATCH 082/176] fix: overlap validation of shoot defaults with seed
networks (#13349)
---
pkg/apis/core/validation/seed.go | 80 ++++++++++---
pkg/apis/core/validation/seed_test.go | 125 +++++++++++++++++----
pkg/utils/validation/cidr/disjoint.go | 58 ++++++----
pkg/utils/validation/cidr/disjoint_test.go | 8 +-
4 files changed, 208 insertions(+), 63 deletions(-)
diff --git a/pkg/apis/core/validation/seed.go b/pkg/apis/core/validation/seed.go
index 9495f9faf3c..8d4b824984e 100644
--- a/pkg/apis/core/validation/seed.go
+++ b/pkg/apis/core/validation/seed.go
@@ -288,46 +288,94 @@ func validateSeedNetworks(seedNetworks core.SeedNetworks, fldPath *field.Path, i
return append(allErrs, errs...)
}
+ // Four buckets: all cidrs, seed cidrs and shoot defaults V4 and V6
+ // - all cidrs: must be valid CIDRs, must not overlap with reserved ranges
+ // - seed cidrs: must not overlap with each other
+ // - shoot defaults (V4): must not overlap with each other
+ // - shoot defaults (V6): must not overlap with each other, must not overlap with seed networks
var (
- primaryIPFamily = helper.DeterminePrimaryIPFamily(seedNetworks.IPFamilies)
- networks []cidrvalidation.CIDR
- reservedSeedServiceRange = cidrvalidation.NewCIDR(v1beta1constants.ReservedKubeApiServerMappingRange, field.NewPath(""))
+ primaryIPFamily = helper.DeterminePrimaryIPFamily(seedNetworks.IPFamilies)
+ allCIDRs []cidrvalidation.CIDR
+ seedCIDRs []cidrvalidation.CIDR
+ shootDefaultsV4 []cidrvalidation.CIDR
+ shootDefaultsV6 []cidrvalidation.CIDR
+ pods cidrvalidation.CIDR
+ services cidrvalidation.CIDR
+ nodes cidrvalidation.CIDR
+ shootPods cidrvalidation.CIDR
+ shootServices cidrvalidation.CIDR
+ reservedKubeApiServerMappingRange = cidrvalidation.NewCIDR(v1beta1constants.ReservedKubeApiServerMappingRange, field.NewPath(""))
)
if !inTemplate || len(seedNetworks.Pods) > 0 {
- networks = append(networks, cidrvalidation.NewCIDR(seedNetworks.Pods, fldPath.Child("pods")))
+ pods = cidrvalidation.NewCIDR(seedNetworks.Pods, fldPath.Child("pods"))
+ allCIDRs = append(allCIDRs, pods)
+ seedCIDRs = append(seedCIDRs, pods)
}
if !inTemplate || len(seedNetworks.Services) > 0 {
- services := cidrvalidation.NewCIDR(seedNetworks.Services, fldPath.Child("services"))
- networks = append(networks, services)
+ services = cidrvalidation.NewCIDR(seedNetworks.Services, fldPath.Child("services"))
+ allCIDRs = append(allCIDRs, services)
+ seedCIDRs = append(seedCIDRs, services)
// Service range must not be larger than /8 for ipv4
if services.IsIPv4() {
- maxSize, _ := reservedSeedServiceRange.GetIPNet().Mask.Size()
+ maxSize, _ := reservedKubeApiServerMappingRange.GetIPNet().Mask.Size()
allErrs = append(allErrs, services.ValidateMaxSize(maxSize)...)
}
}
if seedNetworks.Nodes != nil {
- networks = append(networks, cidrvalidation.NewCIDR(*seedNetworks.Nodes, fldPath.Child("nodes")))
+ nodes = cidrvalidation.NewCIDR(*seedNetworks.Nodes, fldPath.Child("nodes"))
+ allCIDRs = append(allCIDRs, nodes)
+ seedCIDRs = append(seedCIDRs, nodes)
}
if shootDefaults := seedNetworks.ShootDefaults; shootDefaults != nil {
if shootDefaults.Pods != nil {
- networks = append(networks, cidrvalidation.NewCIDR(*shootDefaults.Pods, fldPath.Child("shootDefaults", "pods")))
+ shootPods = cidrvalidation.NewCIDR(*shootDefaults.Pods, fldPath.Child("shootDefaults", "pods"))
+ allCIDRs = append(allCIDRs, shootPods)
+ if shootPods.IsIPv4() {
+ shootDefaultsV4 = append(shootDefaultsV4, shootPods)
+ } else {
+ shootDefaultsV6 = append(shootDefaultsV6, shootPods)
+ }
}
if shootDefaults.Services != nil {
- networks = append(networks, cidrvalidation.NewCIDR(*shootDefaults.Services, fldPath.Child("shootDefaults", "services")))
+ shootServices = cidrvalidation.NewCIDR(*shootDefaults.Services, fldPath.Child("shootDefaults", "services"))
+ allCIDRs = append(allCIDRs, shootServices)
+ if shootServices.IsIPv4() {
+ shootDefaultsV4 = append(shootDefaultsV4, shootServices)
+ } else {
+ shootDefaultsV6 = append(shootDefaultsV6, shootServices)
+ }
}
}
- allErrs = append(allErrs, cidrvalidation.ValidateCIDRParse(networks...)...)
+ // All CIDRs must be valid
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDRParse(allCIDRs...)...)
// Don't check IP family in dualstack case.
if len(seedNetworks.IPFamilies) != 2 {
- allErrs = append(allErrs, cidrvalidation.ValidateCIDRIPFamily(networks, string(primaryIPFamily))...)
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDRIPFamily(allCIDRs, string(primaryIPFamily))...)
+ }
+
+ // In case any IP ranges are incorrect, there is no benefit in checking for intersections.
+ if len(allErrs) > 0 {
+ return allErrs
+ }
+
+ // Seed CIDRs must not overlap with each other
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDROverlap(seedCIDRs, false)...)
+ // Shoot default CIDRs must not overlap with each other
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDROverlap(shootDefaultsV4, false)...)
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDROverlap(shootDefaultsV6, false)...)
+ // Shoot default CIDRs (V6) must not overlap with seed CIDRs
+ for _, seedCIDR := range seedCIDRs {
+ allErrs = append(allErrs, seedCIDR.ValidateNotOverlap(shootDefaultsV6...)...)
}
- allErrs = append(allErrs, cidrvalidation.ValidateCIDROverlap(networks, false)...)
- allErrs = append(allErrs, reservedSeedServiceRange.ValidateNotOverlap(networks...)...)
- vpnRangeV6 := cidrvalidation.NewCIDR(v1beta1constants.DefaultVPNRangeV6, field.NewPath(""))
- allErrs = append(allErrs, vpnRangeV6.ValidateNotOverlap(networks...)...)
+ // All CIDRs must not overlap with reserved ranges
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDROverlapWithReservedRanges(pods, "pod")...)
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDROverlapWithReservedRanges(services, "service")...)
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDROverlapWithReservedRanges(nodes, "node")...)
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDROverlapWithReservedRanges(shootPods, "pod")...)
+ allErrs = append(allErrs, cidrvalidation.ValidateCIDROverlapWithReservedRanges(shootServices, "service")...)
return allErrs
}
diff --git a/pkg/apis/core/validation/seed_test.go b/pkg/apis/core/validation/seed_test.go
index b8ca21de21e..6b7d4ab8d25 100644
--- a/pkg/apis/core/validation/seed_test.go
+++ b/pkg/apis/core/validation/seed_test.go
@@ -420,10 +420,10 @@ var _ = Describe("Seed Validation Tests", func() {
Namespace: "garden",
},
}
- new := seed.DeepCopy()
- new.Spec.DNS.Internal = nil
+ newSeed := seed.DeepCopy()
+ newSeed.Spec.DNS.Internal = nil
- errorList := ValidateSeedUpdate(new, seed)
+ errorList := ValidateSeedUpdate(newSeed, seed)
Expect(errorList).To(ContainElement(PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeForbidden),
"Field": Equal("spec.dns.internal"),
@@ -652,10 +652,10 @@ var _ = Describe("Seed Validation Tests", func() {
},
},
}
- new := seed.DeepCopy()
- new.Spec.DNS.Defaults = nil
+ newSeed := seed.DeepCopy()
+ newSeed.Spec.DNS.Defaults = nil
- errorList := ValidateSeedUpdate(new, seed)
+ errorList := ValidateSeedUpdate(newSeed, seed)
Expect(errorList).To(ContainElement(PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeForbidden),
"Field": Equal("spec.dns.defaults"),
@@ -819,26 +819,27 @@ var _ = Describe("Seed Validation Tests", func() {
}))
})
- It("should forbid Seed with overlapping networks", func() {
- shootDefaultPodCIDR := "10.0.1.128/28" // 10.0.1.128 -> 10.0.1.13
- shootDefaultServiceCIDR := "10.0.1.144/30" // 10.0.1.144 -> 10.0.1.17
+ It("should forbid Seed with overlapping networks but allow overlap with shoot defaults", func() {
+ shootDefaultPodCIDR := "10.0.1.128/28" // 10.0.1.128 -> 10.0.1.143
+ shootDefaultServiceCIDR := "10.0.1.144/30" // 10.0.1.144 -> 10.0.1.147
- nodesCIDR := "10.0.0.0/8" // 10.0.0.0 -> 10.255.255.25
+ nodesCIDR := "10.0.0.0/8" // 10.0.0.0 -> 10.255.255.255
// Pods CIDR overlaps with Nodes network
// Services CIDR overlaps with Nodes and Pods
// Shoot default pod CIDR overlaps with services
// Shoot default pod CIDR overlaps with shoot default pod CIDR
seed.Spec.Networks = core.SeedNetworks{
Nodes: &nodesCIDR, // 10.0.0.0 -> 10.255.255.25
- Pods: "10.0.1.0/24", // 10.0.1.0 -> 10.0.1.25
- Services: "10.0.1.64/26", // 10.0.1.64 -> 10.0.1.17
+ Pods: "10.0.1.0/24", // 10.0.1.0 -> 10.0.1.255
+ Services: "10.0.1.64/26", // 10.0.1.64 -> 10.0.1.127
ShootDefaults: &core.ShootNetworks{
Pods: &shootDefaultPodCIDR,
Services: &shootDefaultServiceCIDR,
},
}
- Expect(ValidateSeed(seed)).To(ConsistOfFields(Fields{
+ errorList := ValidateSeed(seed)
+ Expect(errorList).To(ConsistOfFields(Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.networks.nodes"),
"BadValue": Equal("10.0.0.0/8"),
@@ -849,36 +850,64 @@ var _ = Describe("Seed Validation Tests", func() {
"BadValue": Equal("10.0.0.0/8"),
"Detail": Equal("must not overlap with \"spec.networks.services\" (\"10.0.1.64/26\")"),
}, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.services"),
+ "Detail": Equal(`must not overlap with "spec.networks.pods" ("10.0.1.0/24")`),
+ }))
+
+ Expect(errorList).To(Not(ContainElement(HaveFields(Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.networks.shootDefaults.pods"),
"Detail": Equal(`must not overlap with "spec.networks.nodes" ("10.0.0.0/8")`),
- }, Fields{
+ }))))
+
+ Expect(errorList).To(Not(ContainElement(HaveFields(Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.networks.shootDefaults.services"),
"Detail": Equal(`must not overlap with "spec.networks.nodes" ("10.0.0.0/8")`),
- }, Fields{
- "Type": Equal(field.ErrorTypeInvalid),
- "Field": Equal("spec.networks.services"),
- "Detail": Equal(`must not overlap with "spec.networks.pods" ("10.0.1.0/24")`),
- }, Fields{
+ }))))
+
+ Expect(errorList).To(Not(ContainElement(HaveFields(Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.networks.shootDefaults.pods"),
"Detail": Equal(`must not overlap with "spec.networks.pods" ("10.0.1.0/24")`),
- }, Fields{
+ }))))
+
+ Expect(errorList).To(Not(ContainElement(HaveFields(Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.networks.shootDefaults.services"),
"Detail": Equal(`must not overlap with "spec.networks.pods" ("10.0.1.0/24")`),
- }))
+ }))))
})
- It("should forbid Seed with overlap to reserved range", func() {
+ It("should forbid Seed with overlap to reserved ranges", func() {
// Service CIDR overlaps with reserved range
seed.Spec.Networks.Pods = "240.0.0.0/16" // 240.0.0.0 -> 240.0.255.255
+ seed.Spec.Networks.Services = "243.1.0.0/16"
+ seed.Spec.Networks.Nodes = ptr.To("242.2.0.0/16")
+ seed.Spec.Networks.ShootDefaults.Pods = ptr.To("244.3.0.0/16")
+ seed.Spec.Networks.ShootDefaults.Services = ptr.To("244.4.0.0/16")
Expect(ValidateSeed(seed)).To(ConsistOfFields(Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.networks.pods"),
- "Detail": Equal(`must not overlap with "[]" ("240.0.0.0/8")`),
+ "Detail": Equal(`pod network intersects with reserved kube-apiserver mapping range (240.0.0.0/8)`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.services"),
+ "Detail": Equal(`service network intersects with reserved shoot service network mapping range (243.0.0.0/8)`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.nodes"),
+ "Detail": Equal(`node network intersects with reserved shoot node network mapping range (242.0.0.0/8)`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.shootDefaults.pods"),
+ "Detail": Equal(`pod network intersects with reserved shoot pod network mapping range (244.0.0.0/8)`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.shootDefaults.services"),
+ "Detail": Equal(`service network intersects with reserved shoot pod network mapping range (244.0.0.0/8)`),
}))
})
@@ -941,6 +970,56 @@ var _ = Describe("Seed Validation Tests", func() {
}))
})
+ It("should forbid Seed with overlapping networks", func() {
+ seed.Spec.Networks.Nodes = ptr.To("2001:db8:11::/48")
+ seed.Spec.Networks.Pods = "2001:db8:11:1::/49"
+ seed.Spec.Networks.Services = "2001:db8:11:2::/49"
+ seed.Spec.Networks.ShootDefaults.Pods = ptr.To("2001:db8:11:a::/64")
+ seed.Spec.Networks.ShootDefaults.Services = ptr.To("2001:db8:11:b::/64")
+
+ errorList := ValidateSeed(seed)
+ Expect(errorList).To(ConsistOfFields(Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.nodes"),
+ "BadValue": Equal("2001:db8:11::/48"),
+ "Detail": Equal(`must not overlap with "spec.networks.pods" ("2001:db8:11:1::/49")`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.nodes"),
+ "BadValue": Equal("2001:db8:11::/48"),
+ "Detail": Equal(`must not overlap with "spec.networks.services" ("2001:db8:11:2::/49")`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.services"),
+ "BadValue": Equal("2001:db8:11:2::/49"),
+ "Detail": Equal(`must not overlap with "spec.networks.pods" ("2001:db8:11:1::/49")`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.shootDefaults.pods"),
+ "Detail": Equal(`must not overlap with "spec.networks.pods" ("2001:db8:11:1::/49")`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.shootDefaults.pods"),
+ "Detail": Equal(`must not overlap with "spec.networks.nodes" ("2001:db8:11::/48")`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.shootDefaults.pods"),
+ "Detail": Equal(`must not overlap with "spec.networks.services" ("2001:db8:11:2::/49")`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.shootDefaults.services"),
+ "Detail": Equal(`must not overlap with "spec.networks.nodes" ("2001:db8:11::/48")`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.shootDefaults.services"),
+ "Detail": Equal(`must not overlap with "spec.networks.pods" ("2001:db8:11:1::/49")`),
+ }, Fields{
+ "Type": Equal(field.ErrorTypeInvalid),
+ "Field": Equal("spec.networks.shootDefaults.services"),
+ "Detail": Equal(`must not overlap with "spec.networks.services" ("2001:db8:11:2::/49")`),
+ }))
+ })
+
It("should forbid IPv4 CIDRs with IPv6 IP family", func() {
seed.Spec.Networks.Nodes = ptr.To("10.1.0.0/16")
seed.Spec.Networks.Pods = "10.2.0.0/16"
diff --git a/pkg/utils/validation/cidr/disjoint.go b/pkg/utils/validation/cidr/disjoint.go
index e0eab72daca..477686935cc 100644
--- a/pkg/utils/validation/cidr/disjoint.go
+++ b/pkg/utils/validation/cidr/disjoint.go
@@ -60,33 +60,51 @@ func validateOverlapWithSeed(fldPath *field.Path, shootNetwork []string, network
allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("shoot %s network intersects with seed node network", networkType)))
}
}
+ allErrs = append(allErrs, validateOverlapWithReservedRanges(fldPath, network, networkType)...)
+ }
+ if len(shootNetwork) == 0 && networkRequired {
+ allErrs = append(allErrs, field.Required(fldPath, networkType+"s is required"))
+ }
- if NetworksIntersect(v1beta1constants.DefaultVPNRangeV6, network) {
- allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("shoot %s network intersects with default vpn network (%s)", networkType, v1beta1constants.DefaultVPNRangeV6)))
- }
+ return allErrs
+}
- if NetworksIntersect(v1beta1constants.ReservedKubeApiServerMappingRange, network) {
- allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("shoot %s network intersects with reserved kube-apiserver mapping range (%s)", networkType, v1beta1constants.ReservedKubeApiServerMappingRange)))
- }
+// ValidateCIDROverlapWithReservedRanges validates that the given CIDR does not overlap with reserved ranges.
+func ValidateCIDROverlapWithReservedRanges(cidr CIDR, networkType string) field.ErrorList {
+ allErrs := field.ErrorList{}
- if NetworksIntersect(v1beta1constants.ReservedSeedPodNetworkMappedRange, network) {
- allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("shoot %s network intersects with reserved seed pod network mapping range (%s)", networkType, v1beta1constants.ReservedSeedPodNetworkMappedRange)))
- }
+ if cidr == nil {
+ return allErrs
+ }
+ allErrs = append(allErrs, validateOverlapWithReservedRanges(cidr.GetFieldPath(), cidr.GetCIDR(), networkType)...)
+ return allErrs
+}
- if NetworksIntersect(v1beta1constants.ReservedShootNodeNetworkMappedRange, network) {
- allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("shoot %s network intersects with reserved shoot node network mapping range (%s)", networkType, v1beta1constants.ReservedShootNodeNetworkMappedRange)))
- }
+func validateOverlapWithReservedRanges(fldPath *field.Path, network, networkType string) field.ErrorList {
+ allErrs := field.ErrorList{}
- if NetworksIntersect(v1beta1constants.ReservedShootServiceNetworkMappedRange, network) {
- allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("shoot %s network intersects with reserved shoot service network mapping range (%s)", networkType, v1beta1constants.ReservedShootServiceNetworkMappedRange)))
- }
+ if NetworksIntersect(v1beta1constants.DefaultVPNRangeV6, network) {
+ allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("%s network intersects with default vpn network (%s)", networkType, v1beta1constants.DefaultVPNRangeV6)))
+ }
- if NetworksIntersect(v1beta1constants.ReservedShootPodNetworkMappedRange, network) {
- allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("shoot %s network intersects with reserved shoot pod network mapping range (%s)", networkType, v1beta1constants.ReservedShootPodNetworkMappedRange)))
- }
+ if NetworksIntersect(v1beta1constants.ReservedKubeApiServerMappingRange, network) {
+ allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("%s network intersects with reserved kube-apiserver mapping range (%s)", networkType, v1beta1constants.ReservedKubeApiServerMappingRange)))
}
- if len(shootNetwork) == 0 && networkRequired {
- allErrs = append(allErrs, field.Required(fldPath, networkType+"s is required"))
+
+ if NetworksIntersect(v1beta1constants.ReservedSeedPodNetworkMappedRange, network) {
+ allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("%s network intersects with reserved seed pod network mapping range (%s)", networkType, v1beta1constants.ReservedSeedPodNetworkMappedRange)))
+ }
+
+ if NetworksIntersect(v1beta1constants.ReservedShootNodeNetworkMappedRange, network) {
+ allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("%s network intersects with reserved shoot node network mapping range (%s)", networkType, v1beta1constants.ReservedShootNodeNetworkMappedRange)))
+ }
+
+ if NetworksIntersect(v1beta1constants.ReservedShootServiceNetworkMappedRange, network) {
+ allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("%s network intersects with reserved shoot service network mapping range (%s)", networkType, v1beta1constants.ReservedShootServiceNetworkMappedRange)))
+ }
+
+ if NetworksIntersect(v1beta1constants.ReservedShootPodNetworkMappedRange, network) {
+ allErrs = append(allErrs, field.Invalid(fldPath, network, fmt.Sprintf("%s network intersects with reserved shoot pod network mapping range (%s)", networkType, v1beta1constants.ReservedShootPodNetworkMappedRange)))
}
return allErrs
diff --git a/pkg/utils/validation/cidr/disjoint_test.go b/pkg/utils/validation/cidr/disjoint_test.go
index d2141fbf619..ad6e599451e 100644
--- a/pkg/utils/validation/cidr/disjoint_test.go
+++ b/pkg/utils/validation/cidr/disjoint_test.go
@@ -188,17 +188,17 @@ var _ = Describe("utils", func() {
PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("[].nodes"),
- "Detail": ContainSubstring("shoot node network intersects with reserved shoot service network mapping range (243.0.0.0/8)"),
+ "Detail": ContainSubstring("node network intersects with reserved shoot service network mapping range (243.0.0.0/8)"),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("[].services"),
- "Detail": ContainSubstring("shoot service network intersects with reserved shoot node network mapping range (242.0.0.0/8)"),
+ "Detail": ContainSubstring("service network intersects with reserved shoot node network mapping range (242.0.0.0/8)"),
})),
PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("[].pods"),
- "Detail": ContainSubstring("shoot pod network intersects with reserved seed pod network mapping range (241.0.0.0/8)"),
+ "Detail": ContainSubstring("pod network intersects with reserved seed pod network mapping range (241.0.0.0/8)"),
})),
))
})
@@ -224,7 +224,7 @@ var _ = Describe("utils", func() {
PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("[].pods"),
- "Detail": ContainSubstring("shoot pod network intersects with reserved shoot pod network mapping range (244.0.0.0/8)"),
+ "Detail": ContainSubstring("pod network intersects with reserved shoot pod network mapping range (244.0.0.0/8)"),
})),
))
})
From 931b14a03a99f3b7a9d17c12a2e3c51679463314 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Oliver=20G=C3=B6tz?=
<47362717+oliver-goetz@users.noreply.github.com>
Date: Tue, 11 Nov 2025 19:06:07 +0100
Subject: [PATCH 083/176] Deactivate `UnauthenticatedHTTP2DOSMitigation` for
kube-apiservers where `IstioTLSTermination` is active (#13405)
* Deactivate `UnauthenticatedHTTP2DOSMitigation` feature gate for kube-apiservers where IstioTLSTermination is active
* Tighten `overload.premature_reset_total_stream_count` for istio-ingressgateway
More cautious mitigation of HTTP/2 "Rapid Reset" DoS Vulnerability than default.
---
.../istio-ingress/templates/deployment.yaml | 4 +
.../istio/test_charts/ingress_deployment.yaml | 4 +
pkg/component/shared/kubeapiserver.go | 15 ++++
pkg/component/shared/kubeapiserver_test.go | 79 ++++++++++++-------
.../operation/botanist/kubeapiserver.go | 1 +
.../controller/garden/garden/components.go | 1 +
6 files changed, 74 insertions(+), 30 deletions(-)
diff --git a/pkg/component/networking/istio/charts/istio/istio-ingress/templates/deployment.yaml b/pkg/component/networking/istio/charts/istio/istio-ingress/templates/deployment.yaml
index 94362bf9a1b..9d709f7b21b 100644
--- a/pkg/component/networking/istio/charts/istio/istio-ingress/templates/deployment.yaml
+++ b/pkg/component/networking/istio/charts/istio/istio-ingress/templates/deployment.yaml
@@ -34,6 +34,10 @@ spec:
protocolDetectionTimeout: 100ms
runtimeValues:
"overload.global_downstream_max_connections": "750000"
+ # Limits for mitigating HTTP/2 "Rapid Reset" DoS Vulnerability
+ # See also https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76
+ "overload.premature_reset_total_stream_count": "100"
+ "overload.premature_reset_min_stream_lifetime_seconds": "1"
spec:
serviceAccountName: istio-ingressgateway-service-account
securityContext:
diff --git a/pkg/component/networking/istio/test_charts/ingress_deployment.yaml b/pkg/component/networking/istio/test_charts/ingress_deployment.yaml
index 1aab7cb9ca9..ce6a360a539 100644
--- a/pkg/component/networking/istio/test_charts/ingress_deployment.yaml
+++ b/pkg/component/networking/istio/test_charts/ingress_deployment.yaml
@@ -33,6 +33,10 @@ spec:
protocolDetectionTimeout: 100ms
runtimeValues:
"overload.global_downstream_max_connections": "750000"
+ # Limits for mitigating HTTP/2 "Rapid Reset" DoS Vulnerability
+ # See also https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76
+ "overload.premature_reset_total_stream_count": "100"
+ "overload.premature_reset_min_stream_lifetime_seconds": "1"
spec:
serviceAccountName: istio-ingressgateway-service-account
securityContext:
diff --git a/pkg/component/shared/kubeapiserver.go b/pkg/component/shared/kubeapiserver.go
index e28a9db70f1..d18ddb9ac74 100644
--- a/pkg/component/shared/kubeapiserver.go
+++ b/pkg/component/shared/kubeapiserver.go
@@ -21,6 +21,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/serializer/json"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets"
+ "k8s.io/apiserver/pkg/features"
admissionapiv1 "k8s.io/pod-security-admission/admission/api/v1"
admissionapiv1alpha1 "k8s.io/pod-security-admission/admission/api/v1alpha1"
admissionapiv1beta1 "k8s.io/pod-security-admission/admission/api/v1beta1"
@@ -82,6 +83,7 @@ func NewKubeAPIServer(
priorityClassName string,
isWorkerless bool,
runsAsStaticPod bool,
+ istioTLSTerminationEnabled bool,
auditWebhookConfig *apiserver.AuditWebhook,
authenticationWebhookConfig *kubeapiserver.AuthenticationWebhook,
authorizationWebhookConfigs []kubeapiserver.AuthorizationWebhook,
@@ -160,6 +162,19 @@ func NewKubeAPIServer(
enableAnonymousAuthentication = apiServerConfig.EnableAnonymousAuthentication
}
+ // UnauthenticatedHTTP2DOSMitigation feature gate must be disabled when IstioTLSTermination is enabled.
+ // The mitigation which is implemented in kube-apiserver does not affect the connection from client but only between
+ // istio ingress gateway and kube-apiserver. Therefore, it does not provide any protection but can cause quite some
+ // issues like dropped connections. It is not recommended to have this when using L7 load-balancing.
+ // More details: https://github.com/kubernetes/kubernetes/pull/121120
+ // With IstioTLSTermination enabled, HTTP/2 "Rapid Reset" DoS Vulnerability is mitigated by Envoy measurements.
+ if istioTLSTerminationEnabled {
+ if featureGates == nil {
+ featureGates = make(map[string]bool)
+ }
+ featureGates[string(features.UnauthenticatedHTTP2DOSMitigation)] = false
+ }
+
enabledAdmissionPluginConfigs, err := convertToAdmissionPluginConfigs(ctx, resourceConfigClient, objectMeta.Namespace, enabledAdmissionPlugins)
if err != nil {
return nil, err
diff --git a/pkg/component/shared/kubeapiserver_test.go b/pkg/component/shared/kubeapiserver_test.go
index f48301b902e..46a3fcc3cb9 100644
--- a/pkg/component/shared/kubeapiserver_test.go
+++ b/pkg/component/shared/kubeapiserver_test.go
@@ -79,6 +79,7 @@ var _ = Describe("KubeAPIServer", func() {
authenticationWebhookConfig *kubeapiserver.AuthenticationWebhook
authorizationWebhookConfigs []kubeapiserver.AuthorizationWebhook
resourcesToStoreInETCDEvents []schema.GroupResource
+ istioTLSTerminationEnabled bool
runtimeClientSet kubernetes.Interface
resourceConfigClient client.Client
@@ -97,6 +98,7 @@ var _ = Describe("KubeAPIServer", func() {
isWorkerless = false
runsAsStaticPod = false
auditWebhookConfig = nil
+ istioTLSTerminationEnabled = false
authenticationWebhookConfig = &kubeapiserver.AuthenticationWebhook{Version: ptr.To("authn-version")}
authorizationWebhookConfigs = []kubeapiserver.AuthorizationWebhook{{Name: "custom", Kubeconfig: []byte("bar"), WebhookConfiguration: apiserverv1beta1.WebhookConfiguration{FailurePolicy: "Fail"}}}
resourcesToStoreInETCDEvents = []schema.GroupResource{{Resource: "foo", Group: "bar"}}
@@ -116,7 +118,7 @@ var _ = Describe("KubeAPIServer", func() {
Describe("AnonymousAuthenticationEnabled", func() {
It("should not set the field by default", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().AnonymousAuthenticationEnabled).To(BeNil())
})
@@ -124,7 +126,7 @@ var _ = Describe("KubeAPIServer", func() {
It("should set the field to true if explicitly enabled", func() {
apiServerConfig = &gardencorev1beta1.KubeAPIServerConfig{EnableAnonymousAuthentication: ptr.To(true)}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().AnonymousAuthenticationEnabled).To(PointTo(BeTrue()))
})
@@ -132,7 +134,7 @@ var _ = Describe("KubeAPIServer", func() {
Describe("APIAudiences", func() {
It("should set the field to 'kubernetes' and 'gardener' by default", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().APIAudiences).To(ConsistOf("kubernetes", "gardener"))
})
@@ -141,7 +143,7 @@ var _ = Describe("KubeAPIServer", func() {
apiAudiences := []string{"foo", "bar"}
apiServerConfig = &gardencorev1beta1.KubeAPIServerConfig{APIAudiences: apiAudiences}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().APIAudiences).To(Equal(append(apiAudiences, "gardener")))
})
@@ -150,10 +152,27 @@ var _ = Describe("KubeAPIServer", func() {
apiAudiences := []string{"foo", "bar", "gardener"}
apiServerConfig = &gardencorev1beta1.KubeAPIServerConfig{APIAudiences: apiAudiences}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().APIAudiences).To(Equal(apiAudiences))
})
+
+ It("should deactivate UnauthenticatedHTTP2DOSMitigation feature gate when IstioTLSTermination is active", func() {
+ istioTLSTerminationEnabled = true
+
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(kubeAPIServer.GetValues().FeatureGates).To(HaveKeyWithValue("UnauthenticatedHTTP2DOSMitigation", false))
+ })
+
+ It("should deactivate UnauthenticatedHTTP2DOSMitigation feature gate when IstioTLSTermination is active and it is manually activated", func() {
+ istioTLSTerminationEnabled = true
+ apiServerConfig = &gardencorev1beta1.KubeAPIServerConfig{KubernetesConfig: gardencorev1beta1.KubernetesConfig{FeatureGates: map[string]bool{"UnauthenticatedHTTP2DOSMitigation": true}}}
+
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(kubeAPIServer.GetValues().FeatureGates).To(HaveKeyWithValue("UnauthenticatedHTTP2DOSMitigation", false))
+ })
})
Describe("AdmissionPlugins", func() {
@@ -166,7 +185,7 @@ var _ = Describe("KubeAPIServer", func() {
func(configuredPlugins []gardencorev1beta1.AdmissionPlugin, expectedPlugins []apiserver.AdmissionPluginConfig, isWorkerless bool) {
apiServerConfig.AdmissionPlugins = configuredPlugins
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().EnabledAdmissionPlugins).To(Equal(expectedPlugins))
},
@@ -235,7 +254,7 @@ var _ = Describe("KubeAPIServer", func() {
var expectedDisabledPlugins []gardencorev1beta1.AdmissionPlugin
AfterEach(func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().DisabledAdmissionPlugins).To(Equal(expectedDisabledPlugins))
})
@@ -310,7 +329,7 @@ var _ = Describe("KubeAPIServer", func() {
codec = serializer.NewCodecFactory(runtimeScheme).CodecForVersions(ser, ser, versions, versions)
configData = nil
- kubeAPIServer, err = NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err = NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
})
Context("When the config is nil", func() {
@@ -522,7 +541,7 @@ exemptions:
prepTest()
}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).To(errMatcher)
if kubeAPIServer != nil {
Expect(kubeAPIServer.GetValues().Audit).To(Equal(expectedConfig))
@@ -675,7 +694,7 @@ exemptions:
prepTest()
}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).To(errMatcher)
if kubeAPIServer != nil {
Expect(kubeAPIServer.GetValues().AuthenticationConfiguration).To(Equal(expectedConfig))
@@ -793,7 +812,7 @@ authorizers:
prepTest()
}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).To(errMatcher)
if kubeAPIServer != nil {
Expect(kubeAPIServer.GetValues().AuthorizationWebhooks).To(Equal(expectedWebhooks))
@@ -947,7 +966,7 @@ authorizers:
Describe("DefaultNotReadyTolerationSeconds and DefaultUnreachableTolerationSeconds", func() {
It("should not set the fields", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().DefaultNotReadyTolerationSeconds).To(BeNil())
Expect(kubeAPIServer.GetValues().DefaultUnreachableTolerationSeconds).To(BeNil())
@@ -959,7 +978,7 @@ authorizers:
DefaultUnreachableTolerationSeconds: ptr.To[int64](130),
}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().DefaultNotReadyTolerationSeconds).To(PointTo(Equal(int64(120))))
Expect(kubeAPIServer.GetValues().DefaultUnreachableTolerationSeconds).To(PointTo(Equal(int64(130))))
@@ -968,7 +987,7 @@ authorizers:
Describe("EventTTL", func() {
It("should not set the event ttl field", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().EventTTL).To(BeNil())
})
@@ -980,7 +999,7 @@ authorizers:
EventTTL: eventTTL,
}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().EventTTL).To(Equal(eventTTL))
})
@@ -988,7 +1007,7 @@ authorizers:
Describe("FeatureGates", func() {
It("should set the field to nil by default", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().FeatureGates).To(BeNil())
})
@@ -1002,7 +1021,7 @@ authorizers:
},
}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().FeatureGates).To(Equal(featureGates))
})
@@ -1015,7 +1034,7 @@ authorizers:
prepTest()
}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().OIDC).To(Equal(expectedConfig))
},
@@ -1041,7 +1060,7 @@ authorizers:
Describe("Requests", func() {
It("should set the field to nil by default", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().Requests).To(BeNil())
})
@@ -1053,7 +1072,7 @@ authorizers:
}
apiServerConfig = &gardencorev1beta1.KubeAPIServerConfig{Requests: requests}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().Requests).To(Equal(requests))
})
@@ -1061,7 +1080,7 @@ authorizers:
Describe("RuntimeConfig", func() {
It("should set the field to nil by default", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().RuntimeConfig).To(BeNil())
})
@@ -1070,7 +1089,7 @@ authorizers:
runtimeConfig := map[string]bool{"foo": true, "bar": false}
apiServerConfig = &gardencorev1beta1.KubeAPIServerConfig{RuntimeConfig: runtimeConfig}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().RuntimeConfig).To(Equal(runtimeConfig))
})
@@ -1080,7 +1099,7 @@ authorizers:
It("should set the field to the configured values", func() {
vpnConfig = kubeapiserver.VPNConfig{Enabled: true}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().VPN).To(Equal(vpnConfig))
})
@@ -1088,7 +1107,7 @@ authorizers:
Describe("WatchCacheSizes", func() {
It("should set the field to nil by default", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().WatchCacheSizes).To(BeNil())
})
@@ -1100,7 +1119,7 @@ authorizers:
}
apiServerConfig = &gardencorev1beta1.KubeAPIServerConfig{WatchCacheSizes: watchCacheSizes}
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().WatchCacheSizes).To(Equal(watchCacheSizes))
})
@@ -1108,7 +1127,7 @@ authorizers:
Describe("PriorityClassName", func() {
It("should set the field properly", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().PriorityClassName).To(Equal(priorityClassName))
})
@@ -1116,7 +1135,7 @@ authorizers:
Describe("IsWorkerless", func() {
It("should set the field properly", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().IsWorkerless).To(Equal(isWorkerless))
})
@@ -1124,7 +1143,7 @@ authorizers:
Describe("AuthenticationWebhook", func() {
It("should set the field properly", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().AuthenticationWebhook).To(Equal(authenticationWebhookConfig))
})
@@ -1132,7 +1151,7 @@ authorizers:
Describe("AuthorizationWebhooks", func() {
It("should set the field properly", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().AuthorizationWebhooks).To(Equal(authorizationWebhookConfigs))
})
@@ -1140,7 +1159,7 @@ authorizers:
Describe("ResourcesToStoreInETCDEvents", func() {
It("should set the field properly", func() {
- kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
+ kubeAPIServer, err := NewKubeAPIServer(ctx, runtimeClientSet, resourceConfigClient, namespace, objectMeta, runtimeVersion, targetVersion, sm, namePrefix, apiServerConfig, autoscalingConfig, vpnConfig, priorityClassName, isWorkerless, runsAsStaticPod, istioTLSTerminationEnabled, auditWebhookConfig, authenticationWebhookConfig, authorizationWebhookConfigs, resourcesToStoreInETCDEvents)
Expect(err).NotTo(HaveOccurred())
Expect(kubeAPIServer.GetValues().ResourcesToStoreInETCDEvents).To(Equal(resourcesToStoreInETCDEvents))
})
diff --git a/pkg/gardenlet/operation/botanist/kubeapiserver.go b/pkg/gardenlet/operation/botanist/kubeapiserver.go
index 6f7b01a43f6..a338810d9dc 100644
--- a/pkg/gardenlet/operation/botanist/kubeapiserver.go
+++ b/pkg/gardenlet/operation/botanist/kubeapiserver.go
@@ -65,6 +65,7 @@ func (b *Botanist) DefaultKubeAPIServer(ctx context.Context) (kubeapiserver.Inte
v1beta1constants.PriorityClassNameShootControlPlane500,
b.Shoot.IsWorkerless,
b.Shoot.RunsControlPlane(),
+ b.ShootUsesIstioTLSTermination(),
nil,
nil,
nil,
diff --git a/pkg/operator/controller/garden/garden/components.go b/pkg/operator/controller/garden/garden/components.go
index 8d63407e946..a4f1fd71e9d 100644
--- a/pkg/operator/controller/garden/garden/components.go
+++ b/pkg/operator/controller/garden/garden/components.go
@@ -740,6 +740,7 @@ func (r *Reconciler) newKubeAPIServer(
v1beta1constants.PriorityClassNameGardenSystem500,
true,
false,
+ features.DefaultFeatureGate.Enabled(features.IstioTLSTermination),
auditWebhookConfig,
authenticationWebhookConfig,
authorizationWebhookConfigs,
From 58cf7e471bf13bed2b7bb807d908a50511566a8b Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Tue, 11 Nov 2025 19:06:14 +0100
Subject: [PATCH 084/176] Update module github.com/docker/cli to v29 (#13407)
* Update module github.com/docker/cli to v29
* Run `make tidy`
---------
Co-authored-by: acumino
---
go.mod | 2 +-
go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/go.mod b/go.mod
index 56392687794..9e3ce22e8e6 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
github.com/containerd/errdefs v1.0.0
github.com/coreos/go-systemd/v22 v22.6.0
github.com/distribution/distribution/v3 v3.0.0
- github.com/docker/cli v28.5.2+incompatible
+ github.com/docker/cli v29.0.0+incompatible
github.com/fluent/fluent-operator/v3 v3.5.0
github.com/gardener/cert-management v0.19.0
github.com/gardener/dependency-watchdog v1.6.0
diff --git a/go.sum b/go.sum
index f119bd3bc96..65bb34422df 100644
--- a/go.sum
+++ b/go.sum
@@ -188,8 +188,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
-github.com/docker/cli v28.5.2+incompatible h1:XmG99IHcBmIAoC1PPg9eLBZPlTrNUAijsHLm8PjhBlg=
-github.com/docker/cli v28.5.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
+github.com/docker/cli v29.0.0+incompatible h1:KgsN2RUFMNM8wChxryicn4p46BdQWpXOA1XLGBGPGAw=
+github.com/docker/cli v29.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v28.0.0+incompatible h1:Olh0KS820sJ7nPsBKChVhk5pzqcwDR15fumfAd/p9hM=
From 2f17eb54ddd20be1a88ea576171124e0b1aa1a57 Mon Sep 17 00:00:00 2001
From: Damyan Yordanov
Date: Tue, 11 Nov 2025 20:54:56 +0100
Subject: [PATCH 085/176] Add IPv6 support for `fluent-bit` (#12003)
Enhance `fluent-bit`'s `ConfigMap` to listen on `::`, so both IPv6 and
IPv4 are bound. The change is needed for IronCore, having a single-node
IPv6 setup
---
pkg/component/observability/logging/fluentbit/fluentbit.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/component/observability/logging/fluentbit/fluentbit.go b/pkg/component/observability/logging/fluentbit/fluentbit.go
index 00d86826d76..4298a497462 100644
--- a/pkg/component/observability/logging/fluentbit/fluentbit.go
+++ b/pkg/component/observability/logging/fluentbit/fluentbit.go
@@ -509,7 +509,7 @@ func (f *fluentBit) getClusterFluentBitConfig() *fluentbitv1alpha2.ClusterFluent
LogLevel: "error",
ParsersFile: "parsers.conf",
HttpServer: ptr.To(true),
- HttpListen: "0.0.0.0",
+ HttpListen: "::",
HttpPort: ptr.To[int32](2020),
},
InputSelector: metav1.LabelSelector{
From e6907ca810aadf812cdc6e731f29def2197dfdb3 Mon Sep 17 00:00:00 2001
From: Shafeeque E S
Date: Wed, 12 Nov 2025 01:25:04 +0530
Subject: [PATCH 086/176] Use `kubernetes.io/metadata.name` label instead of
`gardener.cloud/purpose` in GRM webhook namespace selectors (#13398)
---
.../gardener/resourcemanager/resource_manager.go | 2 +-
.../resourcemanager/resource_manager_test.go | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/pkg/component/gardener/resourcemanager/resource_manager.go b/pkg/component/gardener/resourcemanager/resource_manager.go
index b288b84b835..34cae0dd327 100644
--- a/pkg/component/gardener/resourcemanager/resource_manager.go
+++ b/pkg/component/gardener/resourcemanager/resource_manager.go
@@ -1990,7 +1990,7 @@ func (r *resourceManager) buildWebhookNamespaceSelector() *metav1.LabelSelector
return &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{{
- Key: v1beta1constants.GardenerPurpose,
+ Key: corev1.LabelMetadataName,
Operator: operator,
Values: []string{metav1.NamespaceSystem, "kubernetes-dashboard"},
}},
diff --git a/pkg/component/gardener/resourcemanager/resource_manager_test.go b/pkg/component/gardener/resourcemanager/resource_manager_test.go
index dcb3e8f16b8..05f18397f2b 100644
--- a/pkg/component/gardener/resourcemanager/resource_manager_test.go
+++ b/pkg/component/gardener/resourcemanager/resource_manager_test.go
@@ -925,13 +925,13 @@ var _ = Describe("ResourceManager", func() {
switch responsibilityMode {
case ForSource:
namespaceSelectorMatchExpressions = []metav1.LabelSelectorRequirement{{
- Key: "gardener.cloud/purpose",
+ Key: "kubernetes.io/metadata.name",
Operator: metav1.LabelSelectorOpNotIn,
Values: []string{"kube-system", "kubernetes-dashboard"},
}}
case ForTarget:
namespaceSelectorMatchExpressions = []metav1.LabelSelectorRequirement{{
- Key: "gardener.cloud/purpose",
+ Key: "kubernetes.io/metadata.name",
Operator: metav1.LabelSelectorOpIn,
Values: []string{"kube-system", "kubernetes-dashboard"},
}}
@@ -1323,7 +1323,7 @@ webhooks:
name: projected-token-mount.resources.gardener.cloud
namespaceSelector:
matchExpressions:
- - key: gardener.cloud/purpose
+ - key: kubernetes.io/metadata.name
operator: In
values:
- kube-system
@@ -1357,7 +1357,7 @@ webhooks:
name: high-availability-config.resources.gardener.cloud
namespaceSelector:
matchExpressions:
- - key: gardener.cloud/purpose
+ - key: kubernetes.io/metadata.name
operator: In
values:
- kube-system
@@ -1513,7 +1513,7 @@ webhooks:
name: system-components-config.resources.gardener.cloud
namespaceSelector:
matchExpressions:
- - key: gardener.cloud/purpose
+ - key: kubernetes.io/metadata.name
operator: In
values:
- kube-system
@@ -1547,7 +1547,7 @@ webhooks:
name: pod-topology-spread-constraints.resources.gardener.cloud
namespaceSelector:
matchExpressions:
- - key: gardener.cloud/purpose
+ - key: kubernetes.io/metadata.name
operator: In
values:
- kube-system
From 347df6ed91c9c3b532ab37c3021b7805f162a7b3 Mon Sep 17 00:00:00 2001
From: Johannes Scheerer
Date: Tue, 11 Nov 2025 20:55:11 +0100
Subject: [PATCH 087/176] Do not set `Cache{Una,A}uthorizedRequests` fields in
authorization (#13406)
configuration of `kube-apiserver`.
These fields are automatically defaulted, but they are not understood by
older kubernetes releases as they are not present. Therefore, we need to
unset them.
Co-authored-by: Aleksandar Savchev
---
pkg/component/kubernetes/apiserver/authorization.go | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/pkg/component/kubernetes/apiserver/authorization.go b/pkg/component/kubernetes/apiserver/authorization.go
index 44561d61045..33460af7ef5 100644
--- a/pkg/component/kubernetes/apiserver/authorization.go
+++ b/pkg/component/kubernetes/apiserver/authorization.go
@@ -56,6 +56,12 @@ func (k *kubeAPIServer) reconcileConfigMapAuthorizationConfig(ctx context.Contex
}
for _, webhook := range k.values.AuthorizationWebhooks {
+ // For Kubernetes versions < 1.34 the Cache{Una,A}uthorizedRequests fields do not exist.
+ if versionutils.ConstraintK8sLess134.Check(k.values.Version) {
+ webhook.CacheAuthorizedRequests = nil
+ webhook.CacheUnauthorizedRequests = nil
+ }
+
config := apiserverv1beta1.AuthorizerConfiguration{
Type: "Webhook",
Name: webhook.Name,
From 6a6ac663c07f960aaa59a98432457c83e02e3b77 Mon Sep 17 00:00:00 2001
From: Gardener Prow Robot
Date: Wed, 12 Nov 2025 00:16:51 +0100
Subject: [PATCH 088/176] Update module golang.org/x/crypto to v0.44.0 (#13422)
---
go.mod | 10 +++++-----
go.sum | 20 ++++++++++----------
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/go.mod b/go.mod
index 9e3ce22e8e6..a7ddcf13b4c 100644
--- a/go.mod
+++ b/go.mod
@@ -52,9 +52,9 @@ require (
go.uber.org/zap v1.27.0
go.yaml.in/yaml/v2 v2.4.3
go.yaml.in/yaml/v4 v4.0.0-rc.2
- golang.org/x/crypto v0.43.0
+ golang.org/x/crypto v0.44.0
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546
- golang.org/x/text v0.30.0
+ golang.org/x/text v0.31.0
golang.org/x/time v0.14.0
golang.org/x/tools v0.38.0
gomodules.xyz/jsonpatch/v2 v2.5.0
@@ -264,10 +264,10 @@ require (
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.46.0 // indirect
golang.org/x/oauth2 v0.32.0 // indirect
- golang.org/x/sync v0.17.0 // indirect
- golang.org/x/sys v0.37.0 // indirect
+ golang.org/x/sync v0.18.0 // indirect
+ golang.org/x/sys v0.38.0 // indirect
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect
- golang.org/x/term v0.36.0 // indirect
+ golang.org/x/term v0.37.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/grpc v1.76.0 // indirect
diff --git a/go.sum b/go.sum
index 65bb34422df..ce1f18c37da 100644
--- a/go.sum
+++ b/go.sum
@@ -853,8 +853,8 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
-golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
+golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
+golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -916,8 +916,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
-golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
+golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
+golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -941,18 +941,18 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
-golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
+golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU=
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
-golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
-golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
+golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
+golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
-golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
+golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
+golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
From 7fb185dc55a38b32f1fd4e43048f2bce99acb5ea Mon Sep 17 00:00:00 2001
From: Sebastian Stauch
Date: Wed, 12 Nov 2025 09:38:53 +0100
Subject: [PATCH 089/176] Revert "Update dependency kyverno/kyverno to v1.16.0
(#13391)" (#13419)
This reverts commit bc3bc162eabac5ff7e4c407abef5a62711cd6b24.
---
example/provider-extensions/kyverno/kustomization.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/example/provider-extensions/kyverno/kustomization.yaml b/example/provider-extensions/kyverno/kustomization.yaml
index fc5276abbce..ad73a020620 100644
--- a/example/provider-extensions/kyverno/kustomization.yaml
+++ b/example/provider-extensions/kyverno/kustomization.yaml
@@ -2,7 +2,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
-- https://github.com/kyverno/kyverno/releases/download/v1.16.0/install.yaml
+- https://github.com/kyverno/kyverno/releases/download/v1.15.2/install.yaml
- kyverno-poddisruptionbudget.yaml
- kyverno-rbac.yaml
From 8227c0838aa2e6c1e7db0f0c0b306e05eb6d7257 Mon Sep 17 00:00:00 2001
From: Ashwani Kumar
Date: Wed, 12 Nov 2025 15:46:53 +0530
Subject: [PATCH 090/176] Added set of flags for CA nodeGroupBackoff (#13403)
* Added set of flags for nodGroupBackoff
* Addressed review comments
Co-authored-by: Aaron Francis Fernandes <79958509+aaronfern@users.noreply.github.com>
---------
Co-authored-by: Aaron Francis Fernandes <79958509+aaronfern@users.noreply.github.com>
---
docs/api-reference/core.md | 42 +
example/90-shoot.yaml | 3 +
pkg/apis/core/types_shoot.go | 6 +
pkg/apis/core/v1beta1/defaults_shoot.go | 9 +
pkg/apis/core/v1beta1/defaults_shoot_test.go | 73 +-
pkg/apis/core/v1beta1/generated.pb.go | 2008 +++++++++--------
pkg/apis/core/v1beta1/generated.proto | 12 +
pkg/apis/core/v1beta1/types_shoot.go | 9 +
.../core/v1beta1/zz_generated.conversion.go | 6 +
.../core/v1beta1/zz_generated.deepcopy.go | 15 +
pkg/apis/core/validation/shoot.go | 4 +
pkg/apis/core/validation/shoot_test.go | 30 +
pkg/apis/core/zz_generated.deepcopy.go | 15 +
pkg/apiserver/openapi/openapi_generated.go | 18 +
.../clusterautoscaler/cluster_autoscaler.go | 3 +
.../cluster_autoscaler_test.go | 77 +-
16 files changed, 1350 insertions(+), 980 deletions(-)
diff --git a/docs/api-reference/core.md b/docs/api-reference/core.md
index b670753d337..a3562357d69 100644
--- a/docs/api-reference/core.md
+++ b/docs/api-reference/core.md
@@ -4071,6 +4071,48 @@ int32
Default: 1
+