diff --git a/api/v1alpha1/capoperator_types.go b/api/v1alpha1/capoperator_types.go index 6aae954..ba10234 100644 --- a/api/v1alpha1/capoperator_types.go +++ b/api/v1alpha1/capoperator_types.go @@ -82,6 +82,8 @@ type SubscriptionServer struct { type Controller struct { // Optionally enable detailed opertational metrics for the controller by setting this to true DetailedOperationalMetrics bool `json:"detailedOperationalMetrics,omitempty"` + // Configuration of maximum number of concurrent reconciles for the resources managed by the controller + MaxConcurrentReconciles *MaxConcurrentReconciles `json:"maxConcurrentReconciles,omitempty"` // Version monitoring configuration VersionMonitoring *VersionMonitoring `json:"versionMonitoring,omitempty"` // Optionally specify list of additional volumes for the controller pod(s) @@ -90,6 +92,21 @@ type Controller struct { VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"` } +type MaxConcurrentReconciles struct { + // Maximum number of concurrent reconciles for the cap application + CAPApplication string `json:"capApplication,omitempty"` + // Maximum number of concurrent reconciles for the cap application version + CAPApplicationVersion string `json:"capApplicationVersion,omitempty"` + // Maximum number of concurrent reconciles for the cap tenant + CAPTenant string `json:"capTenant,omitempty"` + // Maximum number of concurrent reconciles for the cap tenant operation + CAPTenantOperation string `json:"capTenantOperation,omitempty"` + // Maximum number of concurrent reconciles for the domain + Domain string `json:"domain,omitempty"` + // Maximum number of concurrent reconciles for the cluster domain + ClusterDomain string `json:"clusterDomain,omitempty"` +} + type VersionMonitoring struct { // URL of the Prometheus server from which metrics related to managed application versions can be queried PrometheusAddress string `json:"prometheusAddress,omitempty"` diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index a9bcb1b..12bce8c 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -148,6 +148,11 @@ func (in *CertificateConfig) DeepCopy() *CertificateConfig { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Controller) DeepCopyInto(out *Controller) { *out = *in + if in.MaxConcurrentReconciles != nil { + in, out := &in.MaxConcurrentReconciles, &out.MaxConcurrentReconciles + *out = new(MaxConcurrentReconciles) + **out = **in + } if in.VersionMonitoring != nil { in, out := &in.VersionMonitoring, &out.VersionMonitoring *out = new(VersionMonitoring) @@ -236,6 +241,21 @@ func (in *GrafanaDashboard) DeepCopy() *GrafanaDashboard { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MaxConcurrentReconciles) DeepCopyInto(out *MaxConcurrentReconciles) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MaxConcurrentReconciles. +func (in *MaxConcurrentReconciles) DeepCopy() *MaxConcurrentReconciles { + if in == nil { + return nil + } + out := new(MaxConcurrentReconciles) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Monitoring) DeepCopyInto(out *Monitoring) { *out = *in diff --git a/config/crd/operator.sme.sap.com_capoperators.yaml b/config/crd/operator.sme.sap.com_capoperators.yaml index e3362ef..e970361 100644 --- a/config/crd/operator.sme.sap.com_capoperators.yaml +++ b/config/crd/operator.sme.sap.com_capoperators.yaml @@ -59,6 +59,35 @@ spec: description: Optionally enable detailed opertational metrics for the controller by setting this to true type: boolean + maxConcurrentReconciles: + description: Configuration of maximum number of concurrent reconciles + for the resources managed by the controller + properties: + capApplication: + description: Maximum number of concurrent reconciles for the + cap application + type: string + capApplicationVersion: + description: Maximum number of concurrent reconciles for the + cap application version + type: string + capTenant: + description: Maximum number of concurrent reconciles for the + cap tenant + type: string + capTenantOperation: + description: Maximum number of concurrent reconciles for the + cap tenant operation + type: string + clusterDomain: + description: Maximum number of concurrent reconciles for the + cluster domain + type: string + domain: + description: Maximum number of concurrent reconciles for the + domain + type: string + type: object versionMonitoring: description: Version monitoring configuration properties: diff --git a/internal/transformer/parameter_transformer_test.go b/internal/transformer/parameter_transformer_test.go index 96fb18b..82464e7 100644 --- a/internal/transformer/parameter_transformer_test.go +++ b/internal/transformer/parameter_transformer_test.go @@ -32,6 +32,7 @@ func TestTransformer(t *testing.T) { withControllerVolumes bool withCertManager bool withMonitoringGrafanaDashboard bool + withMaxConcurrentReconciles bool }{ { name: "With dnsTarget and without ingress gateway labels", @@ -63,6 +64,12 @@ func TestTransformer(t *testing.T) { longDomain: false, withoutIngressGatewaySvcAnnotation: true, }, + { + name: "With max concurrent reconciles", + dnsTargetFilled: true, + withMaxConcurrentReconciles: true, + expectError: false, + }, { name: "With version monitoring and dnsTarget filled", dnsTargetFilled: true, @@ -201,6 +208,16 @@ func TestTransformer(t *testing.T) { } } + if tt.withMaxConcurrentReconciles { + capOperatorSpec.Controller.MaxConcurrentReconciles = &v1alpha1.MaxConcurrentReconciles{ + CAPApplication: "2", + CAPApplicationVersion: "5", + CAPTenant: "15", + CAPTenantOperation: "20", + Domain: "1", + } + } + if tt.withVersionMonitoring { capOperatorSpec.Controller.VersionMonitoring = &v1alpha1.VersionMonitoring{ PrometheusAddress: mockPrometheusAddress, @@ -315,6 +332,18 @@ func TestTransformer(t *testing.T) { if transformedController["dnsTarget"].(string) != expectedDnsTarget { t.Error("unexpected value returned for controller.dnsTarget") } + + if tt.withMaxConcurrentReconciles { + if transformedController["maxConcurrentReconciles"] == nil { + t.Error("expected controller.maxConcurrentReconciles to be filled") + } else { + mcr := transformedController["maxConcurrentReconciles"].(map[string]any) + if mcr["capApplication"] != "2" || mcr["capApplicationVersion"] != "5" || mcr["capTenant"] != "15" || mcr["capTenantOperation"] != "20" || mcr["domain"] != "1" { + t.Error("unexpected values returned for controller.maxConcurrentReconciles") + } + } + } + if tt.withVersionMonitoring { if transformedController["versionMonitoring"] == nil { t.Error("expected controller.versionMonitoring to be filled")