bool
diff --git a/hack/api-reference/config.md b/hack/api-reference/config.md
index 45f76ef..453983f 100644
--- a/hack/api-reference/config.md
+++ b/hack/api-reference/config.md
@@ -46,7 +46,9 @@ string
clientConnection
-invalid type
+
+Kubernetes v1alpha1.ClientConnectionConfiguration
+
|
@@ -72,7 +74,9 @@ ETCD
|
healthCheckConfig
-invalid type
+
+github.com/gardener/gardener/extensions/pkg/apis/config/v1alpha1.HealthCheckConfig
+
|
@@ -205,7 +209,9 @@ string
|
capacity
-invalid type
+
+k8s.io/apimachinery/pkg/api/resource.Quantity
+
|
diff --git a/pkg/apis/metal/types_worker.go b/pkg/apis/metal/types_worker.go
index d3bd919..e51fb36 100644
--- a/pkg/apis/metal/types_worker.go
+++ b/pkg/apis/metal/types_worker.go
@@ -4,6 +4,7 @@
package metal
import (
+ corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -47,6 +48,7 @@ type MachineImage struct {
// IgnitionConfig contains ignition settings.
type IgnitionConfig struct {
- Raw string
- Override bool
+ Raw string
+ SecretRef *corev1.LocalObjectReference
+ Override bool
}
diff --git a/pkg/apis/metal/v1alpha1/types_worker.go b/pkg/apis/metal/v1alpha1/types_worker.go
index b7711b3..94ce8d3 100644
--- a/pkg/apis/metal/v1alpha1/types_worker.go
+++ b/pkg/apis/metal/v1alpha1/types_worker.go
@@ -4,6 +4,7 @@
package v1alpha1
import (
+ corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -54,6 +55,10 @@ type IgnitionConfig struct {
// +optional
Raw string `json:"raw,omitempty"`
+ // SecretRef is a reference to a secret containing the ignition config.
+ // +optional
+ SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty"`
+
// Override configures, if ignition keys set by the os-extension are overridden
// by extra ignition.
// +optional
diff --git a/pkg/apis/metal/v1alpha1/zz_generated.conversion.go b/pkg/apis/metal/v1alpha1/zz_generated.conversion.go
index f5b56c3..32bb196 100644
--- a/pkg/apis/metal/v1alpha1/zz_generated.conversion.go
+++ b/pkg/apis/metal/v1alpha1/zz_generated.conversion.go
@@ -12,6 +12,7 @@ import (
unsafe "unsafe"
metal "github.com/ironcore-dev/gardener-extension-provider-metal/pkg/apis/metal"
+ v1 "k8s.io/api/core/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@@ -316,6 +317,7 @@ func Convert_metal_ControlPlaneConfig_To_v1alpha1_ControlPlaneConfig(in *metal.C
func autoConvert_v1alpha1_IgnitionConfig_To_metal_IgnitionConfig(in *IgnitionConfig, out *metal.IgnitionConfig, s conversion.Scope) error {
out.Raw = in.Raw
+ out.SecretRef = (*v1.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
out.Override = in.Override
return nil
}
@@ -327,6 +329,7 @@ func Convert_v1alpha1_IgnitionConfig_To_metal_IgnitionConfig(in *IgnitionConfig,
func autoConvert_metal_IgnitionConfig_To_v1alpha1_IgnitionConfig(in *metal.IgnitionConfig, out *IgnitionConfig, s conversion.Scope) error {
out.Raw = in.Raw
+ out.SecretRef = (*v1.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
out.Override = in.Override
return nil
}
diff --git a/pkg/apis/metal/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/metal/v1alpha1/zz_generated.deepcopy.go
index 63e5e01..520f4cd 100644
--- a/pkg/apis/metal/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/metal/v1alpha1/zz_generated.deepcopy.go
@@ -9,6 +9,7 @@
package v1alpha1
import (
+ v1 "k8s.io/api/core/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@@ -171,6 +172,11 @@ func (in *ControlPlaneConfig) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *IgnitionConfig) DeepCopyInto(out *IgnitionConfig) {
*out = *in
+ if in.SecretRef != nil {
+ in, out := &in.SecretRef, &out.SecretRef
+ *out = new(v1.LocalObjectReference)
+ **out = **in
+ }
return
}
@@ -397,7 +403,7 @@ func (in *WorkerConfig) DeepCopyInto(out *WorkerConfig) {
if in.ExtraIgnition != nil {
in, out := &in.ExtraIgnition, &out.ExtraIgnition
*out = new(IgnitionConfig)
- **out = **in
+ (*in).DeepCopyInto(*out)
}
if in.ExtraServerLabels != nil {
in, out := &in.ExtraServerLabels, &out.ExtraServerLabels
diff --git a/pkg/apis/metal/v1alpha1/zz_generated.defaults.go b/pkg/apis/metal/v1alpha1/zz_generated.defaults.go
index d1bc6c9..b3026ac 100644
--- a/pkg/apis/metal/v1alpha1/zz_generated.defaults.go
+++ b/pkg/apis/metal/v1alpha1/zz_generated.defaults.go
@@ -16,5 +16,16 @@ import (
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
+ scheme.AddTypeDefaultingFunc(&WorkerConfig{}, func(obj interface{}) { SetObjectDefaults_WorkerConfig(obj.(*WorkerConfig)) })
return nil
}
+
+func SetObjectDefaults_WorkerConfig(in *WorkerConfig) {
+ if in.ExtraIgnition != nil {
+ if in.ExtraIgnition.SecretRef != nil {
+ if in.ExtraIgnition.SecretRef.Name == "" {
+ in.ExtraIgnition.SecretRef.Name = ""
+ }
+ }
+ }
+}
diff --git a/pkg/apis/metal/zz_generated.deepcopy.go b/pkg/apis/metal/zz_generated.deepcopy.go
index 4798ad3..f79938b 100644
--- a/pkg/apis/metal/zz_generated.deepcopy.go
+++ b/pkg/apis/metal/zz_generated.deepcopy.go
@@ -9,6 +9,7 @@
package metal
import (
+ v1 "k8s.io/api/core/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@@ -171,6 +172,11 @@ func (in *ControlPlaneConfig) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *IgnitionConfig) DeepCopyInto(out *IgnitionConfig) {
*out = *in
+ if in.SecretRef != nil {
+ in, out := &in.SecretRef, &out.SecretRef
+ *out = new(v1.LocalObjectReference)
+ **out = **in
+ }
return
}
@@ -397,7 +403,7 @@ func (in *WorkerConfig) DeepCopyInto(out *WorkerConfig) {
if in.ExtraIgnition != nil {
in, out := &in.ExtraIgnition, &out.ExtraIgnition
*out = new(IgnitionConfig)
- **out = **in
+ (*in).DeepCopyInto(*out)
}
if in.ExtraServerLabels != nil {
in, out := &in.ExtraServerLabels, &out.ExtraServerLabels
diff --git a/pkg/controller/worker/machines.go b/pkg/controller/worker/machines.go
index d9f77ff..8742c15 100644
--- a/pkg/controller/worker/machines.go
+++ b/pkg/controller/worker/machines.go
@@ -13,11 +13,13 @@ import (
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
"github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
machinecontrollerv1alpha1 "github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1"
+ "github.com/imdario/mergo"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/yaml"
metalv1alpha1 "github.com/ironcore-dev/gardener-extension-provider-metal/pkg/apis/metal/v1alpha1"
"github.com/ironcore-dev/gardener-extension-provider-metal/pkg/metal"
@@ -118,9 +120,14 @@ func (w *workerDelegate) generateMachineClassAndSecrets(ctx context.Context) ([]
metal.ImageFieldName: machineImage,
metal.ServerLabelsFieldName: serverLabels,
}
+
if workerConfig.ExtraIgnition != nil {
- machineClassProviderSpec[metal.IgnitionFieldName] = workerConfig.ExtraIgnition.Raw
- machineClassProviderSpec[metal.IgnitionOverrideFieldName] = workerConfig.ExtraIgnition.Override
+ if mergedIgnition, err := w.mergeIgnitionConfig(ctx, workerConfig); err != nil {
+ return nil, nil, err
+ } else if mergedIgnition != "" {
+ machineClassProviderSpec[metal.IgnitionFieldName] = mergedIgnition
+ machineClassProviderSpec[metal.IgnitionOverrideFieldName] = workerConfig.ExtraIgnition.Override
+ }
}
for zoneIndex, zone := range pool.Zones {
@@ -227,3 +234,53 @@ func (w *workerDelegate) getServerLabelsForMachine(machineType string, workerCon
}
return combinedLabels, nil
}
+
+func (w *workerDelegate) mergeIgnitionConfig(ctx context.Context, workerConfig *metalv1alpha1.WorkerConfig) (string, error) {
+ rawIgnition := &map[string]interface{}{}
+
+ if workerConfig.ExtraIgnition.Raw != "" {
+ if err := yaml.Unmarshal([]byte(workerConfig.ExtraIgnition.Raw), rawIgnition); err != nil {
+ return "", err
+ }
+ }
+
+ if workerConfig.ExtraIgnition.SecretRef != nil {
+ secret := &corev1.Secret{}
+ secretKey := client.ObjectKey{Namespace: w.worker.Namespace, Name: workerConfig.ExtraIgnition.SecretRef.Name}
+ if err := w.client.Get(ctx, secretKey, secret); err != nil {
+ return "", fmt.Errorf("failed to get ignition secret %s: %w", workerConfig.ExtraIgnition.SecretRef, err)
+ }
+
+ secretContent, ok := secret.Data[metal.IgnitionFieldName]
+ if !ok {
+ return "", fmt.Errorf("ignition key not found in secret %s", workerConfig.ExtraIgnition.SecretRef)
+ }
+
+ ignitionSecret := map[string]interface{}{}
+
+ if err := yaml.Unmarshal(secretContent, &ignitionSecret); err != nil {
+ return "", err
+ }
+
+ // append ignition
+ opt := mergo.WithAppendSlice
+
+ // merge both ignitions
+ err := mergo.Merge(rawIgnition, ignitionSecret, opt)
+ if err != nil {
+ return "", err
+ }
+ }
+
+ // avoid converting empty string to an empty map with non-zero length
+ if len(*rawIgnition) == 0 {
+ return "", nil
+ }
+
+ mergedIgnition, err := yaml.Marshal(rawIgnition)
+ if err != nil {
+ return "", err
+ }
+
+ return string(mergedIgnition), nil
+}
diff --git a/pkg/controller/worker/machines_test.go b/pkg/controller/worker/machines_test.go
index 894ea7b..42247be 100644
--- a/pkg/controller/worker/machines_test.go
+++ b/pkg/controller/worker/machines_test.go
@@ -35,6 +35,15 @@ var _ = Describe("Machines", func() {
workerDelegate genericworkeractuator.WorkerDelegate
)
+ dataYml := map[string]any{
+ "a": map[string]any{
+ "b": "foo",
+ "c": "bar",
+ },
+ }
+ yamlString, err := mapToString(dataYml)
+ Expect(err).NotTo(HaveOccurred())
+
BeforeEach(func(ctx SpecContext) {
// TODO: Fix machine pool hashing
workerPoolHash, err := worker.WorkerPoolHash(pool, testCluster, nil, nil)
@@ -76,7 +85,7 @@ var _ = Describe("Machines", func() {
"foo": "bar",
"foo1": "bar1",
},
- metal.IgnitionFieldName: "abc",
+ metal.IgnitionFieldName: yamlString,
metal.IgnitionOverrideFieldName: true,
}
diff --git a/pkg/controller/worker/suite_test.go b/pkg/controller/worker/suite_test.go
index 310c842..32e68e4 100644
--- a/pkg/controller/worker/suite_test.go
+++ b/pkg/controller/worker/suite_test.go
@@ -32,6 +32,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/envtest/komega"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
+ "sigs.k8s.io/yaml"
apiv1alpha1 "github.com/ironcore-dev/gardener-extension-provider-metal/pkg/apis/metal/v1alpha1"
)
@@ -115,6 +116,7 @@ var _ = BeforeSuite(func() {
func SetupTest() (*corev1.Namespace, *gardener.ChartApplier) {
var chartApplier gardener.ChartApplier
ns := &corev1.Namespace{}
+ ign := &corev1.Secret{}
BeforeEach(func(ctx SpecContext) {
var err error
@@ -132,12 +134,44 @@ func SetupTest() (*corev1.Namespace, *gardener.ChartApplier) {
volumeName := "test-volume"
volumeType := "fast"
+ dataYml := map[string]any{
+ "a": map[string]any{
+ "b": "foo",
+ },
+ }
+ yamlString, err := mapToString(dataYml)
+ Expect(err).NotTo(HaveOccurred())
+
+ dataYml2 := map[string]any{
+ "a": map[string]any{
+ "c": "bar",
+ },
+ }
+ yamlString2, err := mapToString(dataYml2)
+ Expect(err).NotTo(HaveOccurred())
+
+ *ign = corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ GenerateName: "testign-",
+ Namespace: ns.Name,
+ },
+ Data: map[string][]byte{
+ "ignition": []byte(yamlString2),
+ },
+ }
+ Expect(k8sClient.Create(ctx, ign)).To(Succeed(), "failed to create test ignition secret")
+ DeferCleanup(k8sClient.Delete, ign)
+
workerConfig = &apiv1alpha1.WorkerConfig{
ExtraServerLabels: map[string]string{
"foo1": "bar1",
},
+
ExtraIgnition: &apiv1alpha1.IgnitionConfig{
- Raw: "abc",
+ Raw: yamlString,
+ SecretRef: &corev1.LocalObjectReference{
+ Name: ign.Name,
+ },
Override: true,
},
}
@@ -251,3 +285,11 @@ func SetupTest() (*corev1.Namespace, *gardener.ChartApplier) {
return ns, &chartApplier
}
+
+func mapToString(m map[string]interface{}) (string, error) {
+ yamlData, err := yaml.Marshal(m)
+ if err != nil {
+ return "", err
+ }
+ return string(yamlData), nil
+}
|