mirror of
https://github.com/cloudnative-pg/plugin-barman-cloud.git
synced 2026-01-12 05:33:11 +01:00
feat(spec): add additionalContainerArgs
Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
This commit is contained in:
parent
62e5441932
commit
551e9663eb
@ -37,6 +37,10 @@ type InstanceSidecarConfiguration struct {
|
|||||||
// Resources define cpu/memory requests and limits for the sidecar that runs in the instance pods.
|
// Resources define cpu/memory requests and limits for the sidecar that runs in the instance pods.
|
||||||
// +optional
|
// +optional
|
||||||
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
|
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
|
||||||
|
|
||||||
|
// AdditionalContainerArgs defines additional arguments to be passed to the sidecar container
|
||||||
|
// +optional
|
||||||
|
AdditionalContainerArgs []string `json:"additionalContainerArgs,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectStoreSpec defines the desired state of ObjectStore.
|
// ObjectStoreSpec defines the desired state of ObjectStore.
|
||||||
|
|||||||
@ -36,6 +36,11 @@ func (in *InstanceSidecarConfiguration) DeepCopyInto(out *InstanceSidecarConfigu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
in.Resources.DeepCopyInto(&out.Resources)
|
in.Resources.DeepCopyInto(&out.Resources)
|
||||||
|
if in.AdditionalContainerArgs != nil {
|
||||||
|
in, out := &in.AdditionalContainerArgs, &out.AdditionalContainerArgs
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceSidecarConfiguration.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceSidecarConfiguration.
|
||||||
|
|||||||
@ -391,6 +391,12 @@ spec:
|
|||||||
description: The configuration for the sidecar that runs in the instance
|
description: The configuration for the sidecar that runs in the instance
|
||||||
pods
|
pods
|
||||||
properties:
|
properties:
|
||||||
|
additionalContainerArgs:
|
||||||
|
description: AdditionalContainerArgs defines additional arguments
|
||||||
|
to be passed to the sidecar container
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
env:
|
env:
|
||||||
description: The environment to be explicitly passed to the sidecar
|
description: The environment to be explicitly passed to the sidecar
|
||||||
items:
|
items:
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import (
|
|||||||
"k8s.io/utils/ptr"
|
"k8s.io/utils/ptr"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"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/metadata"
|
||||||
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
|
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
|
||||||
)
|
)
|
||||||
@ -133,9 +134,10 @@ func (impl LifecycleImplementation) reconcileJob(
|
|||||||
}
|
}
|
||||||
|
|
||||||
type sidecarConfiguration struct {
|
type sidecarConfiguration struct {
|
||||||
env []corev1.EnvVar
|
env []corev1.EnvVar
|
||||||
certificates []corev1.VolumeProjection
|
certificates []corev1.VolumeProjection
|
||||||
resources corev1.ResourceRequirements
|
resources corev1.ResourceRequirements
|
||||||
|
additionalArgs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func reconcileJob(
|
func reconcileJob(
|
||||||
@ -217,14 +219,47 @@ func (impl LifecycleImplementation) reconcilePod(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return reconcilePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{
|
additionalArgs, err := impl.collectAdditionalInstanceArgs(ctx, pluginConfiguration)
|
||||||
env: env,
|
if err != nil {
|
||||||
certificates: certificates,
|
return nil, err
|
||||||
resources: resources,
|
}
|
||||||
|
|
||||||
|
return reconcileInstancePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{
|
||||||
|
env: env,
|
||||||
|
certificates: certificates,
|
||||||
|
resources: resources,
|
||||||
|
additionalArgs: additionalArgs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func reconcilePod(
|
func (impl LifecycleImplementation) collectAdditionalInstanceArgs(
|
||||||
|
ctx context.Context,
|
||||||
|
pluginConfiguration *config.PluginConfiguration,
|
||||||
|
) ([]string, error) {
|
||||||
|
// Prefer the cluster object store (backup/archive). If not set, fallback to the recovery object store.
|
||||||
|
// If neither is configured, no additional args are provided.
|
||||||
|
if len(pluginConfiguration.BarmanObjectName) > 0 {
|
||||||
|
var barmanObjectStore barmancloudv1.ObjectStore
|
||||||
|
if err := impl.Client.Get(ctx, pluginConfiguration.GetBarmanObjectKey(), &barmanObjectStore); err != nil {
|
||||||
|
return nil, fmt.Errorf("while getting barman object store %s: %w",
|
||||||
|
pluginConfiguration.GetBarmanObjectKey().String(), err)
|
||||||
|
}
|
||||||
|
return barmanObjectStore.Spec.InstanceSidecarConfiguration.AdditionalContainerArgs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pluginConfiguration.RecoveryBarmanObjectName) > 0 {
|
||||||
|
var barmanObjectStore barmancloudv1.ObjectStore
|
||||||
|
if err := impl.Client.Get(ctx, pluginConfiguration.GetRecoveryBarmanObjectKey(), &barmanObjectStore); err != nil {
|
||||||
|
return nil, fmt.Errorf("while getting recovery barman object store %s: %w",
|
||||||
|
pluginConfiguration.GetRecoveryBarmanObjectKey().String(), err)
|
||||||
|
}
|
||||||
|
return barmanObjectStore.Spec.InstanceSidecarConfiguration.AdditionalContainerArgs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func reconcileInstancePod(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
cluster *cnpgv1.Cluster,
|
cluster *cnpgv1.Cluster,
|
||||||
request *lifecycle.OperatorLifecycleRequest,
|
request *lifecycle.OperatorLifecycleRequest,
|
||||||
@ -332,6 +367,7 @@ func reconcilePodSpec(
|
|||||||
}
|
}
|
||||||
sidecarTemplate.RestartPolicy = ptr.To(corev1.ContainerRestartPolicyAlways)
|
sidecarTemplate.RestartPolicy = ptr.To(corev1.ContainerRestartPolicyAlways)
|
||||||
sidecarTemplate.Resources = config.resources
|
sidecarTemplate.Resources = config.resources
|
||||||
|
sidecarTemplate.Args = append(sidecarTemplate.Args, config.additionalArgs...)
|
||||||
|
|
||||||
// merge the main container envs if they aren't already set
|
// merge the main container envs if they aren't already set
|
||||||
for _, container := range spec.Containers {
|
for _, container := range spec.Containers {
|
||||||
|
|||||||
@ -6,9 +6,12 @@ import (
|
|||||||
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
|
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
|
||||||
"github.com/cloudnative-pg/cloudnative-pg/pkg/utils"
|
"github.com/cloudnative-pg/cloudnative-pg/pkg/utils"
|
||||||
"github.com/cloudnative-pg/cnpg-i/pkg/lifecycle"
|
"github.com/cloudnative-pg/cnpg-i/pkg/lifecycle"
|
||||||
|
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
|
||||||
batchv1 "k8s.io/api/batch/v1"
|
batchv1 "k8s.io/api/batch/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||||
|
|
||||||
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
|
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
|
||||||
|
|
||||||
@ -18,7 +21,6 @@ import (
|
|||||||
|
|
||||||
var _ = Describe("LifecycleImplementation", func() {
|
var _ = Describe("LifecycleImplementation", func() {
|
||||||
var (
|
var (
|
||||||
lifecycleImpl LifecycleImplementation
|
|
||||||
pluginConfiguration *config.PluginConfiguration
|
pluginConfiguration *config.PluginConfiguration
|
||||||
cluster *cnpgv1.Cluster
|
cluster *cnpgv1.Cluster
|
||||||
jobTypeMeta = metav1.TypeMeta{
|
jobTypeMeta = metav1.TypeMeta{
|
||||||
@ -31,6 +33,26 @@ var _ = Describe("LifecycleImplementation", func() {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// helper to build a fake client with our scheme and optional objects
|
||||||
|
buildClientFunc := func(objs ...runtime.Object) *fake.ClientBuilder {
|
||||||
|
s := runtime.NewScheme()
|
||||||
|
_ = barmancloudv1.AddToScheme(s)
|
||||||
|
return fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(objs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper to create an ObjectStore with given args
|
||||||
|
makeStoreFunc := func(ns, name string, args []string) *barmancloudv1.ObjectStore {
|
||||||
|
return &barmancloudv1.ObjectStore{
|
||||||
|
TypeMeta: metav1.TypeMeta{Kind: "ObjectStore", APIVersion: barmancloudv1.GroupVersion.String()},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns},
|
||||||
|
Spec: barmancloudv1.ObjectStoreSpec{
|
||||||
|
InstanceSidecarConfiguration: barmancloudv1.InstanceSidecarConfiguration{
|
||||||
|
AdditionalContainerArgs: args,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
pluginConfiguration = &config.PluginConfiguration{
|
pluginConfiguration = &config.PluginConfiguration{
|
||||||
BarmanObjectName: "minio-store-dest",
|
BarmanObjectName: "minio-store-dest",
|
||||||
@ -67,6 +89,7 @@ var _ = Describe("LifecycleImplementation", func() {
|
|||||||
|
|
||||||
Describe("GetCapabilities", func() {
|
Describe("GetCapabilities", func() {
|
||||||
It("returns the correct capabilities", func(ctx SpecContext) {
|
It("returns the correct capabilities", func(ctx SpecContext) {
|
||||||
|
var lifecycleImpl LifecycleImplementation
|
||||||
response, err := lifecycleImpl.GetCapabilities(ctx, &lifecycle.OperatorLifecycleCapabilitiesRequest{})
|
response, err := lifecycleImpl.GetCapabilities(ctx, &lifecycle.OperatorLifecycleCapabilitiesRequest{})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(response).NotTo(BeNil())
|
Expect(response).NotTo(BeNil())
|
||||||
@ -76,6 +99,7 @@ var _ = Describe("LifecycleImplementation", func() {
|
|||||||
|
|
||||||
Describe("LifecycleHook", func() {
|
Describe("LifecycleHook", func() {
|
||||||
It("returns an error if object definition is invalid", func(ctx SpecContext) {
|
It("returns an error if object definition is invalid", func(ctx SpecContext) {
|
||||||
|
var lifecycleImpl LifecycleImplementation
|
||||||
request := &lifecycle.OperatorLifecycleRequest{
|
request := &lifecycle.OperatorLifecycleRequest{
|
||||||
ObjectDefinition: []byte("invalid-json"),
|
ObjectDefinition: []byte("invalid-json"),
|
||||||
}
|
}
|
||||||
@ -171,7 +195,7 @@ var _ = Describe("LifecycleImplementation", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("reconcilePod", func() {
|
Describe("reconcileInstancePod", func() {
|
||||||
It("returns a patch for a valid pod", func(ctx SpecContext) {
|
It("returns a patch for a valid pod", func(ctx SpecContext) {
|
||||||
pod := &corev1.Pod{
|
pod := &corev1.Pod{
|
||||||
TypeMeta: podTypeMeta,
|
TypeMeta: podTypeMeta,
|
||||||
@ -185,7 +209,7 @@ var _ = Describe("LifecycleImplementation", func() {
|
|||||||
ObjectDefinition: podJSON,
|
ObjectDefinition: podJSON,
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := reconcilePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{})
|
response, err := reconcileInstancePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(response).NotTo(BeNil())
|
Expect(response).NotTo(BeNil())
|
||||||
Expect(response.JsonPatch).NotTo(BeEmpty())
|
Expect(response.JsonPatch).NotTo(BeEmpty())
|
||||||
@ -203,11 +227,93 @@ var _ = Describe("LifecycleImplementation", func() {
|
|||||||
ObjectDefinition: []byte("invalid-json"),
|
ObjectDefinition: []byte("invalid-json"),
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := reconcilePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{})
|
response, err := reconcileInstancePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{})
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
Expect(response).To(BeNil())
|
Expect(response).To(BeNil())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Describe("collectAdditionalInstanceArgs", func() {
|
||||||
|
It("prefers cluster object store when both are configured", func(ctx SpecContext) {
|
||||||
|
ns := "test-ns"
|
||||||
|
cluster := &cnpgv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: ns}}
|
||||||
|
pc := &config.PluginConfiguration{
|
||||||
|
Cluster: cluster,
|
||||||
|
BarmanObjectName: "primary-store",
|
||||||
|
RecoveryBarmanObjectName: "recovery-store",
|
||||||
|
}
|
||||||
|
primaryArgs := []string{"--primary-a", "--primary-b"}
|
||||||
|
recoveryArgs := []string{"--reco-a"}
|
||||||
|
cli := buildClientFunc(
|
||||||
|
makeStoreFunc(ns, pc.BarmanObjectName, primaryArgs),
|
||||||
|
makeStoreFunc(ns, pc.RecoveryBarmanObjectName, recoveryArgs),
|
||||||
|
).Build()
|
||||||
|
|
||||||
|
impl := LifecycleImplementation{Client: cli}
|
||||||
|
args, err := impl.collectAdditionalInstanceArgs(ctx, pc)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(args).To(Equal(primaryArgs))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("falls back to recovery object store when primary not set", func(ctx SpecContext) {
|
||||||
|
ns := "test-ns"
|
||||||
|
cluster := &cnpgv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: ns}}
|
||||||
|
pc := &config.PluginConfiguration{
|
||||||
|
Cluster: cluster,
|
||||||
|
BarmanObjectName: "",
|
||||||
|
RecoveryBarmanObjectName: "recovery-store",
|
||||||
|
}
|
||||||
|
recoveryArgs := []string{"--reco-x", "--reco-y"}
|
||||||
|
cli := buildClientFunc(
|
||||||
|
makeStoreFunc(ns, pc.RecoveryBarmanObjectName, recoveryArgs),
|
||||||
|
).Build()
|
||||||
|
|
||||||
|
impl := LifecycleImplementation{Client: cli}
|
||||||
|
args, err := impl.collectAdditionalInstanceArgs(ctx, pc)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(args).To(Equal(recoveryArgs))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("returns nil when neither object name is configured", func(ctx SpecContext) {
|
||||||
|
ns := "test-ns"
|
||||||
|
cluster := &cnpgv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: ns}}
|
||||||
|
pc := &config.PluginConfiguration{Cluster: cluster}
|
||||||
|
cli := buildClientFunc().Build()
|
||||||
|
|
||||||
|
impl := LifecycleImplementation{Client: cli}
|
||||||
|
args, err := impl.collectAdditionalInstanceArgs(ctx, pc)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(args).To(BeNil())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("returns error if primary object store cannot be retrieved", func(ctx SpecContext) {
|
||||||
|
ns := "test-ns"
|
||||||
|
cluster := &cnpgv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: ns}}
|
||||||
|
pc := &config.PluginConfiguration{Cluster: cluster, BarmanObjectName: "missing-store"}
|
||||||
|
cli := buildClientFunc().Build()
|
||||||
|
|
||||||
|
impl := LifecycleImplementation{Client: cli}
|
||||||
|
args, err := impl.collectAdditionalInstanceArgs(ctx, pc)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err.Error()).To(ContainSubstring("while getting barman object store"))
|
||||||
|
Expect(err.Error()).To(ContainSubstring(ns + "/" + pc.BarmanObjectName))
|
||||||
|
Expect(args).To(BeNil())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("returns error if recovery object store cannot be retrieved", func(ctx SpecContext) {
|
||||||
|
ns := "test-ns"
|
||||||
|
cluster := &cnpgv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: ns}}
|
||||||
|
pc := &config.PluginConfiguration{Cluster: cluster, RecoveryBarmanObjectName: "missing-reco"}
|
||||||
|
cli := buildClientFunc().Build()
|
||||||
|
|
||||||
|
impl := LifecycleImplementation{Client: cli}
|
||||||
|
args, err := impl.collectAdditionalInstanceArgs(ctx, pc)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err.Error()).To(ContainSubstring("while getting recovery barman object store"))
|
||||||
|
Expect(err.Error()).To(ContainSubstring(ns + "/" + pc.RecoveryBarmanObjectName))
|
||||||
|
Expect(args).To(BeNil())
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
var _ = Describe("Volume utilities", func() {
|
var _ = Describe("Volume utilities", func() {
|
||||||
|
|||||||
@ -390,6 +390,12 @@ spec:
|
|||||||
description: The configuration for the sidecar that runs in the instance
|
description: The configuration for the sidecar that runs in the instance
|
||||||
pods
|
pods
|
||||||
properties:
|
properties:
|
||||||
|
additionalContainerArgs:
|
||||||
|
description: AdditionalContainerArgs defines additional arguments
|
||||||
|
to be passed to the sidecar container
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
env:
|
env:
|
||||||
description: The environment to be explicitly passed to the sidecar
|
description: The environment to be explicitly passed to the sidecar
|
||||||
items:
|
items:
|
||||||
|
|||||||
@ -29,6 +29,7 @@ _Appears in:_
|
|||||||
| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#envvar-v1-core) array_ | The environment to be explicitly passed to the sidecar | | | |
|
| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#envvar-v1-core) array_ | The environment to be explicitly passed to the sidecar | | | |
|
||||||
| `retentionPolicyIntervalSeconds` _integer_ | The retentionCheckInterval defines the frequency at which the<br />system checks and enforces retention policies. | | 1800 | |
|
| `retentionPolicyIntervalSeconds` _integer_ | The retentionCheckInterval defines the frequency at which the<br />system checks and enforces retention policies. | | 1800 | |
|
||||||
| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#resourcerequirements-v1-core)_ | Resources define cpu/memory requests and limits for the sidecar that runs in the instance pods. | | | |
|
| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#resourcerequirements-v1-core)_ | Resources define cpu/memory requests and limits for the sidecar that runs in the instance pods. | | | |
|
||||||
|
| `additionalContainerArgs` _string array_ | AdditionalContainerArgs defines additional arguments to be passed to the sidecar container | | | |
|
||||||
|
|
||||||
|
|
||||||
#### ObjectStore
|
#### ObjectStore
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user