From b038e2e4996cf221dcb1beee9e96eef9017e4d7a Mon Sep 17 00:00:00 2001 From: Leonardo Cecchi Date: Tue, 3 Dec 2024 09:13:03 +0100 Subject: [PATCH] feat: additional environment variables Signed-off-by: Leonardo Cecchi --- api/v1/objectstore_types.go | 6 ++ internal/cnpgi/operator/lifecycle.go | 105 ++++++++++++++++++++-- internal/cnpgi/operator/lifecycle_test.go | 12 +-- internal/cnpgi/operator/start.go | 4 +- 4 files changed, 115 insertions(+), 12 deletions(-) diff --git a/api/v1/objectstore_types.go b/api/v1/objectstore_types.go index 70c2a52..120f5c6 100644 --- a/api/v1/objectstore_types.go +++ b/api/v1/objectstore_types.go @@ -18,6 +18,8 @@ package v1 import ( barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api" + + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -29,6 +31,10 @@ type InstanceSidecarConfiguration struct { // +kubebuilder:validation:Maximum=3600 // +kubebuilder:default=180 CacheTTL *int `json:"cacheTTL,omitempty"` + + // The environment to be explicitely passed to the sidecar + // +optional + Env []corev1.EnvVar `json:"env,omitempty"` } // GetCacheTTL returns the cache TTL value, defaulting to 180 seconds if not set. diff --git a/internal/cnpgi/operator/lifecycle.go b/internal/cnpgi/operator/lifecycle.go index 841ec3c..61a1e5e 100644 --- a/internal/cnpgi/operator/lifecycle.go +++ b/internal/cnpgi/operator/lifecycle.go @@ -14,8 +14,11 @@ import ( "github.com/spf13/viper" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1" "github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata" "github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config" ) @@ -23,6 +26,7 @@ import ( // LifecycleImplementation is the implementation of the lifecycle handler type LifecycleImplementation struct { lifecycle.UnimplementedOperatorLifecycleServer + Client client.Client } // GetCapabilities exposes the lifecycle capabilities @@ -94,20 +98,85 @@ func (impl LifecycleImplementation) LifecycleHook( switch kind { case "Pod": contextLogger.Info("Reconciling pod") - return reconcilePod(ctx, &cluster, request, pluginConfiguration) + return impl.reconcilePod(ctx, &cluster, request, pluginConfiguration) case "Job": contextLogger.Info("Reconciling job") - return reconcileJob(ctx, &cluster, request, pluginConfiguration) + return impl.reconcileJob(ctx, &cluster, request, pluginConfiguration) default: return nil, fmt.Errorf("unsupported kind: %s", kind) } } +func (impl LifecycleImplementation) collectAdditionalEnvs( + ctx context.Context, + namespace string, + pluginConfiguration *config.PluginConfiguration, +) ([]corev1.EnvVar, error) { + var result []corev1.EnvVar + + if len(pluginConfiguration.BarmanObjectName) > 0 { + envs, err := impl.collectObjectStoreEnvs( + ctx, + types.NamespacedName{ + Name: pluginConfiguration.BarmanObjectName, + Namespace: namespace, + }, + ) + if err != nil { + return nil, err + } + result = append(result, envs...) + } + + if len(pluginConfiguration.RecoveryBarmanObjectName) > 0 { + envs, err := impl.collectObjectStoreEnvs( + ctx, + types.NamespacedName{ + Name: pluginConfiguration.RecoveryBarmanObjectName, + Namespace: namespace, + }, + ) + if err != nil { + return nil, err + } + result = append(result, envs...) + } + + return result, nil +} + +func (impl LifecycleImplementation) collectObjectStoreEnvs( + ctx context.Context, + barmanObjectKey types.NamespacedName, +) ([]corev1.EnvVar, error) { + var objectStore barmancloudv1.ObjectStore + if err := impl.Client.Get(ctx, barmanObjectKey, &objectStore); err != nil { + return nil, err + } + + return objectStore.Spec.InstanceSidecarConfiguration.Env, nil +} + +func (impl LifecycleImplementation) reconcileJob( + ctx context.Context, + cluster *cnpgv1.Cluster, + request *lifecycle.OperatorLifecycleRequest, + pluginConfiguration *config.PluginConfiguration, +) (*lifecycle.OperatorLifecycleResponse, error) { + env, err := impl.collectAdditionalEnvs(ctx, cluster.Namespace, pluginConfiguration) + if err != nil { + return nil, nil + } + + return reconcileJob(ctx, cluster, request, pluginConfiguration, env) +} + func reconcileJob( ctx context.Context, cluster *cnpgv1.Cluster, request *lifecycle.OperatorLifecycleRequest, pluginConfiguration *config.PluginConfiguration, + env []corev1.EnvVar, ) (*lifecycle.OperatorLifecycleResponse, error) { contextLogger := log.FromContext(ctx).WithName("lifecycle") if pluginConfig := cluster.GetRecoverySourcePlugin(); pluginConfig == nil || pluginConfig.Name != metadata.PluginName { @@ -144,6 +213,7 @@ func reconcileJob( corev1.Container{ Args: []string{"restore"}, }, + env, ); err != nil { return nil, fmt.Errorf("while reconciling pod spec for job: %w", err) } @@ -159,11 +229,26 @@ func reconcileJob( }, nil } +func (impl LifecycleImplementation) reconcilePod( + ctx context.Context, + cluster *cnpgv1.Cluster, + request *lifecycle.OperatorLifecycleRequest, + pluginConfiguration *config.PluginConfiguration, +) (*lifecycle.OperatorLifecycleResponse, error) { + env, err := impl.collectAdditionalEnvs(ctx, cluster.Namespace, pluginConfiguration) + if err != nil { + return nil, nil + } + + return reconcilePod(ctx, cluster, request, pluginConfiguration, env) +} + func reconcilePod( ctx context.Context, cluster *cnpgv1.Cluster, request *lifecycle.OperatorLifecycleRequest, pluginConfiguration *config.PluginConfiguration, + env []corev1.EnvVar, ) (*lifecycle.OperatorLifecycleResponse, error) { pod, err := decoder.DecodePodJSON(request.GetObjectDefinition()) if err != nil { @@ -176,9 +261,16 @@ func reconcilePod( mutatedPod := pod.DeepCopy() if len(pluginConfiguration.BarmanObjectName) != 0 { - if err := reconcilePodSpec(pluginConfiguration, cluster, &mutatedPod.Spec, "postgres", corev1.Container{ - Args: []string{"instance"}, - }); err != nil { + if err := reconcilePodSpec( + pluginConfiguration, + cluster, + &mutatedPod.Spec, + "postgres", + corev1.Container{ + Args: []string{"instance"}, + }, + env, + ); err != nil { return nil, fmt.Errorf("while reconciling pod spec for pod: %w", err) } } else { @@ -202,6 +294,7 @@ func reconcilePodSpec( spec *corev1.PodSpec, mainContainerName string, sidecarConfig corev1.Container, + additionalEnvs []corev1.EnvVar, ) error { envs := []corev1.EnvVar{ { @@ -246,6 +339,8 @@ func reconcilePodSpec( ) } + envs = append(envs, additionalEnvs...) + baseProbe := &corev1.Probe{ FailureThreshold: 3, ProbeHandler: corev1.ProbeHandler{ diff --git a/internal/cnpgi/operator/lifecycle_test.go b/internal/cnpgi/operator/lifecycle_test.go index 2b59e40..29285eb 100644 --- a/internal/cnpgi/operator/lifecycle_test.go +++ b/internal/cnpgi/operator/lifecycle_test.go @@ -107,7 +107,7 @@ var _ = Describe("LifecycleImplementation", func() { ObjectDefinition: jobJSON, } - response, err := reconcileJob(ctx, cluster, request, pluginConfiguration) + response, err := reconcileJob(ctx, cluster, request, pluginConfiguration, nil) Expect(err).NotTo(HaveOccurred()) Expect(response).NotTo(BeNil()) Expect(response.JsonPatch).NotTo(BeEmpty()) @@ -128,7 +128,7 @@ var _ = Describe("LifecycleImplementation", func() { ObjectDefinition: jobJSON, } - response, err := reconcileJob(ctx, cluster, request, pluginConfiguration) + response, err := reconcileJob(ctx, cluster, request, pluginConfiguration, nil) Expect(err).NotTo(HaveOccurred()) Expect(response).To(BeNil()) }) @@ -138,7 +138,7 @@ var _ = Describe("LifecycleImplementation", func() { ObjectDefinition: []byte("invalid-json"), } - response, err := reconcileJob(ctx, cluster, request, pluginConfiguration) + response, err := reconcileJob(ctx, cluster, request, pluginConfiguration, nil) Expect(err).To(HaveOccurred()) Expect(response).To(BeNil()) }) @@ -165,7 +165,7 @@ var _ = Describe("LifecycleImplementation", func() { ObjectDefinition: jobJSON, } - response, err := reconcileJob(ctx, cluster, request, pluginConfiguration) + response, err := reconcileJob(ctx, cluster, request, pluginConfiguration, nil) Expect(err).NotTo(HaveOccurred()) Expect(response).To(BeNil()) }) @@ -185,7 +185,7 @@ var _ = Describe("LifecycleImplementation", func() { ObjectDefinition: podJSON, } - response, err := reconcilePod(ctx, cluster, request, pluginConfiguration) + response, err := reconcilePod(ctx, cluster, request, pluginConfiguration, nil) Expect(err).NotTo(HaveOccurred()) Expect(response).NotTo(BeNil()) Expect(response.JsonPatch).NotTo(BeEmpty()) @@ -203,7 +203,7 @@ var _ = Describe("LifecycleImplementation", func() { ObjectDefinition: []byte("invalid-json"), } - response, err := reconcilePod(ctx, cluster, request, pluginConfiguration) + response, err := reconcilePod(ctx, cluster, request, pluginConfiguration, nil) Expect(err).To(HaveOccurred()) Expect(response).To(BeNil()) }) diff --git a/internal/cnpgi/operator/start.go b/internal/cnpgi/operator/start.go index 3c8eff6..f7c59be 100644 --- a/internal/cnpgi/operator/start.go +++ b/internal/cnpgi/operator/start.go @@ -27,7 +27,9 @@ func (c *CNPGI) Start(ctx context.Context) error { reconciler.RegisterReconcilerHooksServer(server, ReconcilerImplementation{ Client: c.Client, }) - lifecycle.RegisterOperatorLifecycleServer(server, LifecycleImplementation{}) + lifecycle.RegisterOperatorLifecycleServer(server, LifecycleImplementation{ + Client: c.Client, + }) return nil }