chore: review

Signed-off-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com>
This commit is contained in:
Leonardo Cecchi 2025-05-05 14:19:11 +02:00 committed by Marco Nenciarini
parent 0cf55b8398
commit 91e98994d2
9 changed files with 176 additions and 54 deletions

View File

@ -33,6 +33,7 @@ README
RPO RPO
RTO RTO
RecoveryWindow RecoveryWindow
ResourceRequirements
RetentionPolicy RetentionPolicy
SAS SAS
SFO SFO
@ -64,6 +65,7 @@ cmctl
cnpg cnpg
codebase codebase
containerPort containerPort
cpu
creds creds
csi csi
customresourcedefinition customresourcedefinition

View File

@ -33,6 +33,7 @@ type InstanceSidecarConfiguration struct {
// +kubebuilder:default:=1800 // +kubebuilder:default:=1800
// +optional // +optional
RetentionPolicyIntervalSeconds int `json:"retentionPolicyIntervalSeconds,omitempty"` RetentionPolicyIntervalSeconds int `json:"retentionPolicyIntervalSeconds,omitempty"`
// 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"`

View File

@ -35,6 +35,7 @@ func (in *InstanceSidecarConfiguration) DeepCopyInto(out *InstanceSidecarConfigu
(*in)[i].DeepCopyInto(&(*out)[i]) (*in)[i].DeepCopyInto(&(*out)[i])
} }
} }
in.Resources.DeepCopyInto(&out.Resources)
} }
// 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.

View File

@ -511,18 +511,41 @@ spec:
- name - name
type: object type: object
type: array type: array
retentionPolicyIntervalSeconds:
default: 1800
description: |-
The retentionCheckInterval defines the frequency at which the
system checks and enforces retention policies.
type: integer
resources: resources:
description: |- description: Resources define cpu/memory requests and limits for
Plugin's sidecar resources requirements. Please refer to the sidecar that runs in the instance pods.
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
for more information.
properties: properties:
claims:
description: |-
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
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
items:
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
properties:
name:
description: |-
Name must match the name of one entry in pod.spec.resourceClaims of
the Pod where this field is used. It makes that resource available
inside a container.
type: string
request:
description: |-
Request is the name chosen for a request in the referenced claim.
If empty, everything from the claim is made available, otherwise
only the result of this request.
type: string
required:
- name
type: object
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
limits: limits:
additionalProperties: additionalProperties:
anyOf: anyOf:
@ -548,6 +571,12 @@ spec:
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object type: object
type: object type: object
retentionPolicyIntervalSeconds:
default: 1800
description: |-
The retentionCheckInterval defines the frequency at which the
system checks and enforces retention policies.
type: integer
type: object type: object
retentionPolicy: retentionPolicy:
description: |- description: |-

View File

@ -6,6 +6,13 @@ spec:
retentionPolicy: "1m" retentionPolicy: "1m"
instanceSidecarConfiguration: instanceSidecarConfiguration:
retentionPolicyIntervalSeconds: 30 retentionPolicyIntervalSeconds: 30
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
configuration: configuration:
endpointCA: endpointCA:
name: minio-server-tls name: minio-server-tls

View File

@ -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"
) )
@ -123,15 +124,29 @@ func (impl LifecycleImplementation) reconcileJob(
return nil, err return nil, err
} }
return reconcileJob(ctx, cluster, request, env, certificates) resources, err := impl.collectSidecarResources(ctx, pluginConfiguration)
if err != nil {
return nil, err
}
return reconcileJob(ctx, cluster, request, sidecarConfiguration{
env: env,
certificates: certificates,
resources: resources,
})
}
type sidecarConfiguration struct {
env []corev1.EnvVar
certificates []corev1.VolumeProjection
resources corev1.ResourceRequirements
} }
func reconcileJob( func reconcileJob(
ctx context.Context, ctx context.Context,
cluster *cnpgv1.Cluster, cluster *cnpgv1.Cluster,
request *lifecycle.OperatorLifecycleRequest, request *lifecycle.OperatorLifecycleRequest,
env []corev1.EnvVar, config sidecarConfiguration,
certificates []corev1.VolumeProjection,
) (*lifecycle.OperatorLifecycleResponse, error) { ) (*lifecycle.OperatorLifecycleResponse, error) {
contextLogger := log.FromContext(ctx).WithName("lifecycle") contextLogger := log.FromContext(ctx).WithName("lifecycle")
if pluginConfig := cluster.GetRecoverySourcePlugin(); pluginConfig == nil || pluginConfig.Name != metadata.PluginName { if pluginConfig := cluster.GetRecoverySourcePlugin(); pluginConfig == nil || pluginConfig.Name != metadata.PluginName {
@ -139,7 +154,6 @@ func reconcileJob(
return nil, nil return nil, nil
} }
var barmanObjectStore barmancloudv1.ObjectStore
var job batchv1.Job var job batchv1.Job
if err := decoder.DecodeObjectStrict( if err := decoder.DecodeObjectStrict(
request.GetObjectDefinition(), request.GetObjectDefinition(),
@ -170,9 +184,7 @@ func reconcileJob(
corev1.Container{ corev1.Container{
Args: []string{"restore"}, Args: []string{"restore"},
}, },
env, config,
certificates,
barmanObjectStore,
); err != nil { ); err != nil {
return nil, fmt.Errorf("while reconciling pod spec for job: %w", err) return nil, fmt.Errorf("while reconciling pod spec for job: %w", err)
} }
@ -204,13 +216,28 @@ func (impl LifecycleImplementation) reconcilePod(
return nil, err return nil, err
} }
var barmanObjectStore barmancloudv1.ObjectStore resources, err := impl.collectSidecarResources(ctx, pluginConfiguration)
configuration := config.NewFromCluster(cluster) if err != nil {
if err := impl.Client.Get(ctx, configuration.GetBarmanObjectKey(), &barmanObjectStore); err != nil {
return nil, err return nil, err
} }
return reconcilePod(ctx, cluster, request, pluginConfiguration, env, certificates, barmanObjectStore) return reconcilePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{
env: env,
certificates: certificates,
resources: resources,
})
}
func (impl LifecycleImplementation) collectSidecarResources(
ctx context.Context,
configuration *config.PluginConfiguration,
) (corev1.ResourceRequirements, error) {
var barmanObjectStore barmancloudv1.ObjectStore
if err := impl.Client.Get(ctx, configuration.GetBarmanObjectKey(), &barmanObjectStore); err != nil {
return corev1.ResourceRequirements{}, err
}
return barmanObjectStore.Spec.InstanceSidecarConfiguration.Resources, nil
} }
func reconcilePod( func reconcilePod(
@ -218,9 +245,7 @@ func reconcilePod(
cluster *cnpgv1.Cluster, cluster *cnpgv1.Cluster,
request *lifecycle.OperatorLifecycleRequest, request *lifecycle.OperatorLifecycleRequest,
pluginConfiguration *config.PluginConfiguration, pluginConfiguration *config.PluginConfiguration,
env []corev1.EnvVar, config sidecarConfiguration,
certificates []corev1.VolumeProjection,
barmanObjectStore barmancloudv1.ObjectStore,
) (*lifecycle.OperatorLifecycleResponse, error) { ) (*lifecycle.OperatorLifecycleResponse, error) {
pod, err := decoder.DecodePodJSON(request.GetObjectDefinition()) pod, err := decoder.DecodePodJSON(request.GetObjectDefinition())
if err != nil { if err != nil {
@ -241,9 +266,7 @@ func reconcilePod(
corev1.Container{ corev1.Container{
Args: []string{"instance"}, Args: []string{"instance"},
}, },
env, config,
certificates,
barmanObjectStore,
); err != nil { ); err != nil {
return nil, fmt.Errorf("while reconciling pod spec for pod: %w", err) return nil, fmt.Errorf("while reconciling pod spec for pod: %w", err)
} }
@ -266,10 +289,8 @@ func reconcilePodSpec(
cluster *cnpgv1.Cluster, cluster *cnpgv1.Cluster,
spec *corev1.PodSpec, spec *corev1.PodSpec,
mainContainerName string, mainContainerName string,
sidecarConfig corev1.Container, sidecarTemplate corev1.Container,
additionalEnvs []corev1.EnvVar, config sidecarConfiguration,
certificates []corev1.VolumeProjection,
barmanObjectStore barmancloudv1.ObjectStore,
) error { ) error {
envs := []corev1.EnvVar{ envs := []corev1.EnvVar{
{ {
@ -296,7 +317,7 @@ func reconcilePodSpec(
}, },
} }
envs = append(envs, additionalEnvs...) envs = append(envs, config.env...)
baseProbe := &corev1.Probe{ baseProbe := &corev1.Probe{
FailureThreshold: 10, FailureThreshold: 10,
@ -309,11 +330,11 @@ func reconcilePodSpec(
} }
// fixed values // fixed values
sidecarConfig.Name = "plugin-barman-cloud" sidecarTemplate.Name = "plugin-barman-cloud"
sidecarConfig.Image = viper.GetString("sidecar-image") sidecarTemplate.Image = viper.GetString("sidecar-image")
sidecarConfig.ImagePullPolicy = cluster.Spec.ImagePullPolicy sidecarTemplate.ImagePullPolicy = cluster.Spec.ImagePullPolicy
sidecarConfig.StartupProbe = baseProbe.DeepCopy() sidecarTemplate.StartupProbe = baseProbe.DeepCopy()
sidecarConfig.SecurityContext = &corev1.SecurityContext{ sidecarTemplate.SecurityContext = &corev1.SecurityContext{
AllowPrivilegeEscalation: ptr.To(false), AllowPrivilegeEscalation: ptr.To(false),
RunAsNonRoot: ptr.To(true), RunAsNonRoot: ptr.To(true),
Privileged: ptr.To(false), Privileged: ptr.To(false),
@ -325,21 +346,21 @@ func reconcilePodSpec(
Drop: []corev1.Capability{"ALL"}, Drop: []corev1.Capability{"ALL"},
}, },
} }
sidecarConfig.Resources = barmanObjectStore.Spec.InstanceSidecarConfiguration.Resources sidecarTemplate.Resources = config.resources
// 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 {
if container.Name == mainContainerName { if container.Name == mainContainerName {
for _, env := range container.Env { for _, env := range container.Env {
found := false found := false
for _, existingEnv := range sidecarConfig.Env { for _, existingEnv := range sidecarTemplate.Env {
if existingEnv.Name == env.Name { if existingEnv.Name == env.Name {
found = true found = true
break break
} }
} }
if !found { if !found {
sidecarConfig.Env = append(sidecarConfig.Env, env) sidecarTemplate.Env = append(sidecarTemplate.Env, env)
} }
} }
break break
@ -349,18 +370,18 @@ func reconcilePodSpec(
// merge the default envs if they aren't already set // merge the default envs if they aren't already set
for _, env := range envs { for _, env := range envs {
found := false found := false
for _, existingEnv := range sidecarConfig.Env { for _, existingEnv := range sidecarTemplate.Env {
if existingEnv.Name == env.Name { if existingEnv.Name == env.Name {
found = true found = true
break break
} }
} }
if !found { if !found {
sidecarConfig.Env = append(sidecarConfig.Env, env) sidecarTemplate.Env = append(sidecarTemplate.Env, env)
} }
} }
if err := injectPluginSidecarPodSpec(spec, &sidecarConfig, mainContainerName); err != nil { if err := injectPluginSidecarPodSpec(spec, &sidecarTemplate, mainContainerName); err != nil {
return err return err
} }
@ -370,7 +391,7 @@ func reconcilePodSpec(
Name: barmanCertificatesVolumeName, Name: barmanCertificatesVolumeName,
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
Projected: &corev1.ProjectedVolumeSource{ Projected: &corev1.ProjectedVolumeSource{
Sources: certificates, Sources: config.certificates,
}, },
}, },
}) })

View File

@ -107,7 +107,7 @@ var _ = Describe("LifecycleImplementation", func() {
ObjectDefinition: jobJSON, ObjectDefinition: jobJSON,
} }
response, err := reconcileJob(ctx, cluster, request, nil, nil) response, err := reconcileJob(ctx, cluster, request, 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())
@ -128,7 +128,7 @@ var _ = Describe("LifecycleImplementation", func() {
ObjectDefinition: jobJSON, ObjectDefinition: jobJSON,
} }
response, err := reconcileJob(ctx, cluster, request, nil, nil) response, err := reconcileJob(ctx, cluster, request, sidecarConfiguration{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(response).To(BeNil()) Expect(response).To(BeNil())
}) })
@ -138,7 +138,7 @@ var _ = Describe("LifecycleImplementation", func() {
ObjectDefinition: []byte("invalid-json"), ObjectDefinition: []byte("invalid-json"),
} }
response, err := reconcileJob(ctx, cluster, request, nil, nil) response, err := reconcileJob(ctx, cluster, request, sidecarConfiguration{})
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(response).To(BeNil()) Expect(response).To(BeNil())
}) })
@ -165,7 +165,7 @@ var _ = Describe("LifecycleImplementation", func() {
ObjectDefinition: jobJSON, ObjectDefinition: jobJSON,
} }
response, err := reconcileJob(ctx, cluster, request, nil, nil) response, err := reconcileJob(ctx, cluster, request, sidecarConfiguration{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(response).To(BeNil()) Expect(response).To(BeNil())
}) })
@ -185,7 +185,7 @@ var _ = Describe("LifecycleImplementation", func() {
ObjectDefinition: podJSON, ObjectDefinition: podJSON,
} }
response, err := reconcilePod(ctx, cluster, request, pluginConfiguration, nil, nil) response, err := reconcilePod(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,7 +203,7 @@ var _ = Describe("LifecycleImplementation", func() {
ObjectDefinition: []byte("invalid-json"), ObjectDefinition: []byte("invalid-json"),
} }
response, err := reconcilePod(ctx, cluster, request, pluginConfiguration, nil, nil) response, err := reconcilePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{})
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(response).To(BeNil()) Expect(response).To(BeNil())
}) })

View File

@ -510,6 +510,66 @@ spec:
- name - name
type: object type: object
type: array type: array
resources:
description: Resources define cpu/memory requests and limits for
the sidecar that runs in the instance pods.
properties:
claims:
description: |-
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
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
items:
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
properties:
name:
description: |-
Name must match the name of one entry in pod.spec.resourceClaims of
the Pod where this field is used. It makes that resource available
inside a container.
type: string
request:
description: |-
Request is the name chosen for a request in the referenced claim.
If empty, everything from the claim is made available, otherwise
only the result of this request.
type: string
required:
- name
type: object
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
limits:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: |-
Limits describes the maximum amount of compute resources allowed.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
requests:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: |-
Requests describes the minimum amount of compute resources required.
If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
otherwise to an implementation-defined value. Requests cannot exceed Limits.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
type: object
retentionPolicyIntervalSeconds: retentionPolicyIntervalSeconds:
default: 1800 default: 1800
description: |- description: |-

View File

@ -28,6 +28,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. | | | |
#### ObjectStore #### ObjectStore