From 6257ea040aa42644385b000947bacd5387377214 Mon Sep 17 00:00:00 2001 From: rriski Date: Thu, 11 Jan 2024 13:16:24 +0200 Subject: [PATCH] feat(service): add service tech email support (#576) --- CHANGELOG.md | 18 ++++++ api/v1alpha1/common.go | 10 +++ api/v1alpha1/zz_generated.deepcopy.go | 20 ++++++ .../templates/aiven.io_cassandras.yaml | 15 +++++ .../templates/aiven.io_clickhouses.yaml | 15 +++++ .../templates/aiven.io_grafanas.yaml | 15 +++++ .../templates/aiven.io_kafkaconnects.yaml | 15 +++++ .../templates/aiven.io_kafkas.yaml | 15 +++++ .../templates/aiven.io_mysqls.yaml | 15 +++++ .../templates/aiven.io_opensearches.yaml | 15 +++++ .../templates/aiven.io_postgresqls.yaml | 15 +++++ .../templates/aiven.io_redis.yaml | 15 +++++ config/crd/bases/aiven.io_cassandras.yaml | 15 +++++ config/crd/bases/aiven.io_clickhouses.yaml | 15 +++++ config/crd/bases/aiven.io_grafanas.yaml | 15 +++++ config/crd/bases/aiven.io_kafkaconnects.yaml | 15 +++++ config/crd/bases/aiven.io_kafkas.yaml | 15 +++++ config/crd/bases/aiven.io_mysqls.yaml | 15 +++++ config/crd/bases/aiven.io_opensearches.yaml | 15 +++++ config/crd/bases/aiven.io_postgresqls.yaml | 15 +++++ config/crd/bases/aiven.io_redis.yaml | 15 +++++ controllers/generic_service_handler.go | 7 +++ docs/docs/api-reference/cassandra.md | 11 ++++ docs/docs/api-reference/clickhouse.md | 11 ++++ docs/docs/api-reference/grafana.md | 11 ++++ docs/docs/api-reference/kafka.md | 11 ++++ docs/docs/api-reference/kafkaconnect.md | 11 ++++ docs/docs/api-reference/mysql.md | 11 ++++ docs/docs/api-reference/opensearch.md | 11 ++++ docs/docs/api-reference/postgresql.md | 11 ++++ docs/docs/api-reference/redis.md | 11 ++++ tests/mysql_test.go | 61 +++++++++++++++++-- 32 files changed, 481 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab9020c5..0f03f7a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,24 @@ - Add `OpenSearch` field `userConfig.opensearch.enable_security_audit`, type `boolean`: Enable/Disable security audit +- Add `Cassandra` field `technicalEmails`, type `array`: Defines the email addresses that will receive + alerts about upcoming maintenance updates or warnings about service instability +- Add `Clickhouse` field `technicalEmails`, type `array`: Defines the email addresses that will receive + alerts about upcoming maintenance updates or warnings about service instability +- Add `Grafana` field `technicalEmails`, type `array`: Defines the email addresses that will receive + alerts about upcoming maintenance updates or warnings about service instability +- Add `KafkaConnect` field `technicalEmails`, type `array`: Defines the email addresses that will receive + alerts about upcoming maintenance updates or warnings about service instability +- Add `Kafka` field `technicalEmails`, type `array`: Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability +- Add `MySQL` field `technicalEmails`, type `array`: Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability +- Add `OpenSearch` field `technicalEmails`, type `array`: Defines the email addresses that will receive + alerts about upcoming maintenance updates or warnings about service instability +- Add `PostgreSQL` field `technicalEmails`, type `array`: Defines the email addresses that will receive + alerts about upcoming maintenance updates or warnings about service instability +- Add `Redis` field `technicalEmails`, type `array`: Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability ## v0.16.1 - 2023-12-15 diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index 9e8216ed..da272704 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -47,6 +47,12 @@ type ServiceStatus struct { State string `json:"state,omitempty"` } +type ServiceTechEmail struct { + // +kubebuilder:validation:Format="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" + // Email address. + Email string `json:"email"` +} + type ServiceCommonSpec struct { // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Format="^[a-zA-Z0-9_-]*$" @@ -87,6 +93,10 @@ type ServiceCommonSpec struct { // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable" // Service integrations to specify when creating a service. Not applied after initial service creation ServiceIntegrations []*ServiceIntegrationItem `json:"serviceIntegrations,omitempty"` + + // +kubebuilder:validation:MaxItems=10 + // Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + TechnicalEmails []ServiceTechEmail `json:"technicalEmails,omitempty"` } // Validate runs complex validation on ServiceCommonSpec diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 3fa865d1..cff735f4 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -2025,6 +2025,11 @@ func (in *ServiceCommonSpec) DeepCopyInto(out *ServiceCommonSpec) { } } } + if in.TechnicalEmails != nil { + in, out := &in.TechnicalEmails, &out.TechnicalEmails + *out = make([]ServiceTechEmail, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceCommonSpec. @@ -2220,6 +2225,21 @@ func (in *ServiceStatus) DeepCopy() *ServiceStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceTechEmail) DeepCopyInto(out *ServiceTechEmail) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceTechEmail. +func (in *ServiceTechEmail) DeepCopy() *ServiceTechEmail { + if in == nil { + return nil + } + out := new(ServiceTechEmail) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceUser) DeepCopyInto(out *ServiceUser) { *out = *in diff --git a/charts/aiven-operator-crds/templates/aiven.io_cassandras.yaml b/charts/aiven-operator-crds/templates/aiven.io_cassandras.yaml index c77cf9c8..c35851d4 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_cassandras.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_cassandras.yaml @@ -188,6 +188,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/charts/aiven-operator-crds/templates/aiven.io_clickhouses.yaml b/charts/aiven-operator-crds/templates/aiven.io_clickhouses.yaml index 631948cd..5779dde0 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_clickhouses.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_clickhouses.yaml @@ -174,6 +174,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/charts/aiven-operator-crds/templates/aiven.io_grafanas.yaml b/charts/aiven-operator-crds/templates/aiven.io_grafanas.yaml index 17a7362e..160acecf 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_grafanas.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_grafanas.yaml @@ -188,6 +188,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/charts/aiven-operator-crds/templates/aiven.io_kafkaconnects.yaml b/charts/aiven-operator-crds/templates/aiven.io_kafkaconnects.yaml index 8ff70dac..ee2ed732 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_kafkaconnects.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_kafkaconnects.yaml @@ -140,6 +140,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/charts/aiven-operator-crds/templates/aiven.io_kafkas.yaml b/charts/aiven-operator-crds/templates/aiven.io_kafkas.yaml index ea73fcba..d93745eb 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_kafkas.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_kafkas.yaml @@ -195,6 +195,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/charts/aiven-operator-crds/templates/aiven.io_mysqls.yaml b/charts/aiven-operator-crds/templates/aiven.io_mysqls.yaml index d9232633..ac1556ac 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_mysqls.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_mysqls.yaml @@ -188,6 +188,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/charts/aiven-operator-crds/templates/aiven.io_opensearches.yaml b/charts/aiven-operator-crds/templates/aiven.io_opensearches.yaml index 8a403e83..3595098a 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_opensearches.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_opensearches.yaml @@ -174,6 +174,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/charts/aiven-operator-crds/templates/aiven.io_postgresqls.yaml b/charts/aiven-operator-crds/templates/aiven.io_postgresqls.yaml index 75804c65..a6497c73 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_postgresqls.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_postgresqls.yaml @@ -188,6 +188,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/charts/aiven-operator-crds/templates/aiven.io_redis.yaml b/charts/aiven-operator-crds/templates/aiven.io_redis.yaml index bd6c988d..f0ddc8d6 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_redis.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_redis.yaml @@ -174,6 +174,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/config/crd/bases/aiven.io_cassandras.yaml b/config/crd/bases/aiven.io_cassandras.yaml index c77cf9c8..c35851d4 100644 --- a/config/crd/bases/aiven.io_cassandras.yaml +++ b/config/crd/bases/aiven.io_cassandras.yaml @@ -188,6 +188,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/config/crd/bases/aiven.io_clickhouses.yaml b/config/crd/bases/aiven.io_clickhouses.yaml index 631948cd..5779dde0 100644 --- a/config/crd/bases/aiven.io_clickhouses.yaml +++ b/config/crd/bases/aiven.io_clickhouses.yaml @@ -174,6 +174,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/config/crd/bases/aiven.io_grafanas.yaml b/config/crd/bases/aiven.io_grafanas.yaml index 17a7362e..160acecf 100644 --- a/config/crd/bases/aiven.io_grafanas.yaml +++ b/config/crd/bases/aiven.io_grafanas.yaml @@ -188,6 +188,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/config/crd/bases/aiven.io_kafkaconnects.yaml b/config/crd/bases/aiven.io_kafkaconnects.yaml index 8ff70dac..ee2ed732 100644 --- a/config/crd/bases/aiven.io_kafkaconnects.yaml +++ b/config/crd/bases/aiven.io_kafkaconnects.yaml @@ -140,6 +140,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/config/crd/bases/aiven.io_kafkas.yaml b/config/crd/bases/aiven.io_kafkas.yaml index ea73fcba..d93745eb 100644 --- a/config/crd/bases/aiven.io_kafkas.yaml +++ b/config/crd/bases/aiven.io_kafkas.yaml @@ -195,6 +195,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/config/crd/bases/aiven.io_mysqls.yaml b/config/crd/bases/aiven.io_mysqls.yaml index d9232633..ac1556ac 100644 --- a/config/crd/bases/aiven.io_mysqls.yaml +++ b/config/crd/bases/aiven.io_mysqls.yaml @@ -188,6 +188,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/config/crd/bases/aiven.io_opensearches.yaml b/config/crd/bases/aiven.io_opensearches.yaml index 8a403e83..3595098a 100644 --- a/config/crd/bases/aiven.io_opensearches.yaml +++ b/config/crd/bases/aiven.io_opensearches.yaml @@ -174,6 +174,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/config/crd/bases/aiven.io_postgresqls.yaml b/config/crd/bases/aiven.io_postgresqls.yaml index 75804c65..a6497c73 100644 --- a/config/crd/bases/aiven.io_postgresqls.yaml +++ b/config/crd/bases/aiven.io_postgresqls.yaml @@ -188,6 +188,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/config/crd/bases/aiven.io_redis.yaml b/config/crd/bases/aiven.io_redis.yaml index bd6c988d..f0ddc8d6 100644 --- a/config/crd/bases/aiven.io_redis.yaml +++ b/config/crd/bases/aiven.io_redis.yaml @@ -174,6 +174,21 @@ spec: Tags are key-value pairs that allow you to categorize services. type: object + technicalEmails: + description: + Defines the email addresses that will receive alerts + about upcoming maintenance updates or warnings about service instability. + items: + properties: + email: + description: Email address. + format: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ + type: string + required: + - email + type: object + maxItems: 10 + type: array terminationProtection: description: Prevent service from being deleted. It is recommended diff --git a/controllers/generic_service_handler.go b/controllers/generic_service_handler.go index 56d6318b..677c58c8 100644 --- a/controllers/generic_service_handler.go +++ b/controllers/generic_service_handler.go @@ -48,6 +48,11 @@ func (h *genericServiceHandler) createOrUpdate(ctx context.Context, avn *aiven.C return fmt.Errorf("failed to fetch service: %w", err) } + technicalEmails := make([]aiven.ContactEmail, 0) + for _, email := range spec.TechnicalEmails { + technicalEmails = append(technicalEmails, aiven.ContactEmail(email)) + } + // Creates if not exists or updates existing service var reason string if !exists { @@ -68,6 +73,7 @@ func (h *genericServiceHandler) createOrUpdate(ctx context.Context, avn *aiven.C ServiceType: o.getServiceType(), TerminationProtection: fromAnyPointer(spec.TerminationProtection), UserConfig: userConfig, + TechnicalEmails: &technicalEmails, } for _, s := range spec.ServiceIntegrations { @@ -98,6 +104,7 @@ func (h *genericServiceHandler) createOrUpdate(ctx context.Context, avn *aiven.C ProjectVPCID: toOptionalStringPointer(projectVPCID), TerminationProtection: fromAnyPointer(spec.TerminationProtection), UserConfig: userConfig, + TechnicalEmails: &technicalEmails, } _, err = avn.Services.Update(ctx, spec.Project, ometa.Name, req) if err != nil { diff --git a/docs/docs/api-reference/cassandra.md b/docs/docs/api-reference/cassandra.md index f38393ef..5ad1afed 100644 --- a/docs/docs/api-reference/cassandra.md +++ b/docs/docs/api-reference/cassandra.md @@ -73,6 +73,7 @@ CassandraSpec defines the desired state of Cassandra. - [`projectVpcId`](#spec.projectVpcId-property){: name='spec.projectVpcId-property'} (string, MaxLength: 36). Identifier of the VPC the service should be in, if any. - [`serviceIntegrations`](#spec.serviceIntegrations-property){: name='spec.serviceIntegrations-property'} (array of objects, Immutable, MaxItems: 1). Service integrations to specify when creating a service. Not applied after initial service creation. See below for [nested schema](#spec.serviceIntegrations). - [`tags`](#spec.tags-property){: name='spec.tags-property'} (object, AdditionalProperties: string). Tags are key-value pairs that allow you to categorize services. +- [`technicalEmails`](#spec.technicalEmails-property){: name='spec.technicalEmails-property'} (array of objects, MaxItems: 10). Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. See below for [nested schema](#spec.technicalEmails). - [`terminationProtection`](#spec.terminationProtection-property){: name='spec.terminationProtection-property'} (boolean). Prevent service from being deleted. It is recommended to have this enabled for all services. - [`userConfig`](#spec.userConfig-property){: name='spec.userConfig-property'} (object). Cassandra specific user configuration options. See below for [nested schema](#spec.userConfig). @@ -128,6 +129,16 @@ Service integrations to specify when creating a service. Not applied after initi - [`integrationType`](#spec.serviceIntegrations.integrationType-property){: name='spec.serviceIntegrations.integrationType-property'} (string, Enum: `read_replica`). - [`sourceServiceName`](#spec.serviceIntegrations.sourceServiceName-property){: name='spec.serviceIntegrations.sourceServiceName-property'} (string, MinLength: 1, MaxLength: 64). +## technicalEmails {: #spec.technicalEmails } + +_Appears on [`spec`](#spec)._ + +Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + +**Required** + +- [`email`](#spec.technicalEmails.email-property){: name='spec.technicalEmails.email-property'} (string, Format: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`). Email address. + ## userConfig {: #spec.userConfig } _Appears on [`spec`](#spec)._ diff --git a/docs/docs/api-reference/clickhouse.md b/docs/docs/api-reference/clickhouse.md index 87834973..fdd0dd43 100644 --- a/docs/docs/api-reference/clickhouse.md +++ b/docs/docs/api-reference/clickhouse.md @@ -64,6 +64,7 @@ ClickhouseSpec defines the desired state of Clickhouse. - [`projectVpcId`](#spec.projectVpcId-property){: name='spec.projectVpcId-property'} (string, MaxLength: 36). Identifier of the VPC the service should be in, if any. - [`serviceIntegrations`](#spec.serviceIntegrations-property){: name='spec.serviceIntegrations-property'} (array of objects, Immutable, MaxItems: 1). Service integrations to specify when creating a service. Not applied after initial service creation. See below for [nested schema](#spec.serviceIntegrations). - [`tags`](#spec.tags-property){: name='spec.tags-property'} (object, AdditionalProperties: string). Tags are key-value pairs that allow you to categorize services. +- [`technicalEmails`](#spec.technicalEmails-property){: name='spec.technicalEmails-property'} (array of objects, MaxItems: 10). Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. See below for [nested schema](#spec.technicalEmails). - [`terminationProtection`](#spec.terminationProtection-property){: name='spec.terminationProtection-property'} (boolean). Prevent service from being deleted. It is recommended to have this enabled for all services. - [`userConfig`](#spec.userConfig-property){: name='spec.userConfig-property'} (object). OpenSearch specific user configuration options. See below for [nested schema](#spec.userConfig). @@ -119,6 +120,16 @@ Service integrations to specify when creating a service. Not applied after initi - [`integrationType`](#spec.serviceIntegrations.integrationType-property){: name='spec.serviceIntegrations.integrationType-property'} (string, Enum: `read_replica`). - [`sourceServiceName`](#spec.serviceIntegrations.sourceServiceName-property){: name='spec.serviceIntegrations.sourceServiceName-property'} (string, MinLength: 1, MaxLength: 64). +## technicalEmails {: #spec.technicalEmails } + +_Appears on [`spec`](#spec)._ + +Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + +**Required** + +- [`email`](#spec.technicalEmails.email-property){: name='spec.technicalEmails.email-property'} (string, Format: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`). Email address. + ## userConfig {: #spec.userConfig } _Appears on [`spec`](#spec)._ diff --git a/docs/docs/api-reference/grafana.md b/docs/docs/api-reference/grafana.md index 1dc1c816..d3bf3192 100644 --- a/docs/docs/api-reference/grafana.md +++ b/docs/docs/api-reference/grafana.md @@ -72,6 +72,7 @@ GrafanaSpec defines the desired state of Grafana. - [`projectVpcId`](#spec.projectVpcId-property){: name='spec.projectVpcId-property'} (string, MaxLength: 36). Identifier of the VPC the service should be in, if any. - [`serviceIntegrations`](#spec.serviceIntegrations-property){: name='spec.serviceIntegrations-property'} (array of objects, Immutable, MaxItems: 1). Service integrations to specify when creating a service. Not applied after initial service creation. See below for [nested schema](#spec.serviceIntegrations). - [`tags`](#spec.tags-property){: name='spec.tags-property'} (object, AdditionalProperties: string). Tags are key-value pairs that allow you to categorize services. +- [`technicalEmails`](#spec.technicalEmails-property){: name='spec.technicalEmails-property'} (array of objects, MaxItems: 10). Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. See below for [nested schema](#spec.technicalEmails). - [`terminationProtection`](#spec.terminationProtection-property){: name='spec.terminationProtection-property'} (boolean). Prevent service from being deleted. It is recommended to have this enabled for all services. - [`userConfig`](#spec.userConfig-property){: name='spec.userConfig-property'} (object). Cassandra specific user configuration options. See below for [nested schema](#spec.userConfig). @@ -127,6 +128,16 @@ Service integrations to specify when creating a service. Not applied after initi - [`integrationType`](#spec.serviceIntegrations.integrationType-property){: name='spec.serviceIntegrations.integrationType-property'} (string, Enum: `read_replica`). - [`sourceServiceName`](#spec.serviceIntegrations.sourceServiceName-property){: name='spec.serviceIntegrations.sourceServiceName-property'} (string, MinLength: 1, MaxLength: 64). +## technicalEmails {: #spec.technicalEmails } + +_Appears on [`spec`](#spec)._ + +Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + +**Required** + +- [`email`](#spec.technicalEmails.email-property){: name='spec.technicalEmails.email-property'} (string, Format: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`). Email address. + ## userConfig {: #spec.userConfig } _Appears on [`spec`](#spec)._ diff --git a/docs/docs/api-reference/kafka.md b/docs/docs/api-reference/kafka.md index a1038224..27088fd4 100644 --- a/docs/docs/api-reference/kafka.md +++ b/docs/docs/api-reference/kafka.md @@ -65,6 +65,7 @@ KafkaSpec defines the desired state of Kafka. - [`projectVpcId`](#spec.projectVpcId-property){: name='spec.projectVpcId-property'} (string, MaxLength: 36). Identifier of the VPC the service should be in, if any. - [`serviceIntegrations`](#spec.serviceIntegrations-property){: name='spec.serviceIntegrations-property'} (array of objects, Immutable, MaxItems: 1). Service integrations to specify when creating a service. Not applied after initial service creation. See below for [nested schema](#spec.serviceIntegrations). - [`tags`](#spec.tags-property){: name='spec.tags-property'} (object, AdditionalProperties: string). Tags are key-value pairs that allow you to categorize services. +- [`technicalEmails`](#spec.technicalEmails-property){: name='spec.technicalEmails-property'} (array of objects, MaxItems: 10). Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. See below for [nested schema](#spec.technicalEmails). - [`terminationProtection`](#spec.terminationProtection-property){: name='spec.terminationProtection-property'} (boolean). Prevent service from being deleted. It is recommended to have this enabled for all services. - [`userConfig`](#spec.userConfig-property){: name='spec.userConfig-property'} (object). Kafka specific user configuration options. See below for [nested schema](#spec.userConfig). @@ -120,6 +121,16 @@ Service integrations to specify when creating a service. Not applied after initi - [`integrationType`](#spec.serviceIntegrations.integrationType-property){: name='spec.serviceIntegrations.integrationType-property'} (string, Enum: `read_replica`). - [`sourceServiceName`](#spec.serviceIntegrations.sourceServiceName-property){: name='spec.serviceIntegrations.sourceServiceName-property'} (string, MinLength: 1, MaxLength: 64). +## technicalEmails {: #spec.technicalEmails } + +_Appears on [`spec`](#spec)._ + +Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + +**Required** + +- [`email`](#spec.technicalEmails.email-property){: name='spec.technicalEmails.email-property'} (string, Format: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`). Email address. + ## userConfig {: #spec.userConfig } _Appears on [`spec`](#spec)._ diff --git a/docs/docs/api-reference/kafkaconnect.md b/docs/docs/api-reference/kafkaconnect.md index d045e98b..7340f051 100644 --- a/docs/docs/api-reference/kafkaconnect.md +++ b/docs/docs/api-reference/kafkaconnect.md @@ -57,6 +57,7 @@ KafkaConnectSpec defines the desired state of KafkaConnect. - [`projectVpcId`](#spec.projectVpcId-property){: name='spec.projectVpcId-property'} (string, MaxLength: 36). Identifier of the VPC the service should be in, if any. - [`serviceIntegrations`](#spec.serviceIntegrations-property){: name='spec.serviceIntegrations-property'} (array of objects, Immutable, MaxItems: 1). Service integrations to specify when creating a service. Not applied after initial service creation. See below for [nested schema](#spec.serviceIntegrations). - [`tags`](#spec.tags-property){: name='spec.tags-property'} (object, AdditionalProperties: string). Tags are key-value pairs that allow you to categorize services. +- [`technicalEmails`](#spec.technicalEmails-property){: name='spec.technicalEmails-property'} (array of objects, MaxItems: 10). Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. See below for [nested schema](#spec.technicalEmails). - [`terminationProtection`](#spec.terminationProtection-property){: name='spec.terminationProtection-property'} (boolean). Prevent service from being deleted. It is recommended to have this enabled for all services. - [`userConfig`](#spec.userConfig-property){: name='spec.userConfig-property'} (object). KafkaConnect specific user configuration options. See below for [nested schema](#spec.userConfig). @@ -96,6 +97,16 @@ Service integrations to specify when creating a service. Not applied after initi - [`integrationType`](#spec.serviceIntegrations.integrationType-property){: name='spec.serviceIntegrations.integrationType-property'} (string, Enum: `read_replica`). - [`sourceServiceName`](#spec.serviceIntegrations.sourceServiceName-property){: name='spec.serviceIntegrations.sourceServiceName-property'} (string, MinLength: 1, MaxLength: 64). +## technicalEmails {: #spec.technicalEmails } + +_Appears on [`spec`](#spec)._ + +Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + +**Required** + +- [`email`](#spec.technicalEmails.email-property){: name='spec.technicalEmails.email-property'} (string, Format: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`). Email address. + ## userConfig {: #spec.userConfig } _Appears on [`spec`](#spec)._ diff --git a/docs/docs/api-reference/mysql.md b/docs/docs/api-reference/mysql.md index b7f7d431..8e76ef6e 100644 --- a/docs/docs/api-reference/mysql.md +++ b/docs/docs/api-reference/mysql.md @@ -72,6 +72,7 @@ MySQLSpec defines the desired state of MySQL. - [`projectVpcId`](#spec.projectVpcId-property){: name='spec.projectVpcId-property'} (string, MaxLength: 36). Identifier of the VPC the service should be in, if any. - [`serviceIntegrations`](#spec.serviceIntegrations-property){: name='spec.serviceIntegrations-property'} (array of objects, Immutable, MaxItems: 1). Service integrations to specify when creating a service. Not applied after initial service creation. See below for [nested schema](#spec.serviceIntegrations). - [`tags`](#spec.tags-property){: name='spec.tags-property'} (object, AdditionalProperties: string). Tags are key-value pairs that allow you to categorize services. +- [`technicalEmails`](#spec.technicalEmails-property){: name='spec.technicalEmails-property'} (array of objects, MaxItems: 10). Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. See below for [nested schema](#spec.technicalEmails). - [`terminationProtection`](#spec.terminationProtection-property){: name='spec.terminationProtection-property'} (boolean). Prevent service from being deleted. It is recommended to have this enabled for all services. - [`userConfig`](#spec.userConfig-property){: name='spec.userConfig-property'} (object). MySQL specific user configuration options. See below for [nested schema](#spec.userConfig). @@ -127,6 +128,16 @@ Service integrations to specify when creating a service. Not applied after initi - [`integrationType`](#spec.serviceIntegrations.integrationType-property){: name='spec.serviceIntegrations.integrationType-property'} (string, Enum: `read_replica`). - [`sourceServiceName`](#spec.serviceIntegrations.sourceServiceName-property){: name='spec.serviceIntegrations.sourceServiceName-property'} (string, MinLength: 1, MaxLength: 64). +## technicalEmails {: #spec.technicalEmails } + +_Appears on [`spec`](#spec)._ + +Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + +**Required** + +- [`email`](#spec.technicalEmails.email-property){: name='spec.technicalEmails.email-property'} (string, Format: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`). Email address. + ## userConfig {: #spec.userConfig } _Appears on [`spec`](#spec)._ diff --git a/docs/docs/api-reference/opensearch.md b/docs/docs/api-reference/opensearch.md index c80cf540..928a4c4a 100644 --- a/docs/docs/api-reference/opensearch.md +++ b/docs/docs/api-reference/opensearch.md @@ -65,6 +65,7 @@ OpenSearchSpec defines the desired state of OpenSearch. - [`projectVpcId`](#spec.projectVpcId-property){: name='spec.projectVpcId-property'} (string, MaxLength: 36). Identifier of the VPC the service should be in, if any. - [`serviceIntegrations`](#spec.serviceIntegrations-property){: name='spec.serviceIntegrations-property'} (array of objects, Immutable, MaxItems: 1). Service integrations to specify when creating a service. Not applied after initial service creation. See below for [nested schema](#spec.serviceIntegrations). - [`tags`](#spec.tags-property){: name='spec.tags-property'} (object, AdditionalProperties: string). Tags are key-value pairs that allow you to categorize services. +- [`technicalEmails`](#spec.technicalEmails-property){: name='spec.technicalEmails-property'} (array of objects, MaxItems: 10). Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. See below for [nested schema](#spec.technicalEmails). - [`terminationProtection`](#spec.terminationProtection-property){: name='spec.terminationProtection-property'} (boolean). Prevent service from being deleted. It is recommended to have this enabled for all services. - [`userConfig`](#spec.userConfig-property){: name='spec.userConfig-property'} (object). OpenSearch specific user configuration options. See below for [nested schema](#spec.userConfig). @@ -120,6 +121,16 @@ Service integrations to specify when creating a service. Not applied after initi - [`integrationType`](#spec.serviceIntegrations.integrationType-property){: name='spec.serviceIntegrations.integrationType-property'} (string, Enum: `read_replica`). - [`sourceServiceName`](#spec.serviceIntegrations.sourceServiceName-property){: name='spec.serviceIntegrations.sourceServiceName-property'} (string, MinLength: 1, MaxLength: 64). +## technicalEmails {: #spec.technicalEmails } + +_Appears on [`spec`](#spec)._ + +Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + +**Required** + +- [`email`](#spec.technicalEmails.email-property){: name='spec.technicalEmails.email-property'} (string, Format: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`). Email address. + ## userConfig {: #spec.userConfig } _Appears on [`spec`](#spec)._ diff --git a/docs/docs/api-reference/postgresql.md b/docs/docs/api-reference/postgresql.md index 0f0578eb..0c85f88f 100644 --- a/docs/docs/api-reference/postgresql.md +++ b/docs/docs/api-reference/postgresql.md @@ -67,6 +67,7 @@ PostgreSQLSpec defines the desired state of postgres instance. - [`projectVpcId`](#spec.projectVpcId-property){: name='spec.projectVpcId-property'} (string, MaxLength: 36). Identifier of the VPC the service should be in, if any. - [`serviceIntegrations`](#spec.serviceIntegrations-property){: name='spec.serviceIntegrations-property'} (array of objects, Immutable, MaxItems: 1). Service integrations to specify when creating a service. Not applied after initial service creation. See below for [nested schema](#spec.serviceIntegrations). - [`tags`](#spec.tags-property){: name='spec.tags-property'} (object, AdditionalProperties: string). Tags are key-value pairs that allow you to categorize services. +- [`technicalEmails`](#spec.technicalEmails-property){: name='spec.technicalEmails-property'} (array of objects, MaxItems: 10). Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. See below for [nested schema](#spec.technicalEmails). - [`terminationProtection`](#spec.terminationProtection-property){: name='spec.terminationProtection-property'} (boolean). Prevent service from being deleted. It is recommended to have this enabled for all services. - [`userConfig`](#spec.userConfig-property){: name='spec.userConfig-property'} (object). PostgreSQL specific user configuration options. See below for [nested schema](#spec.userConfig). @@ -122,6 +123,16 @@ Service integrations to specify when creating a service. Not applied after initi - [`integrationType`](#spec.serviceIntegrations.integrationType-property){: name='spec.serviceIntegrations.integrationType-property'} (string, Enum: `read_replica`). - [`sourceServiceName`](#spec.serviceIntegrations.sourceServiceName-property){: name='spec.serviceIntegrations.sourceServiceName-property'} (string, MinLength: 1, MaxLength: 64). +## technicalEmails {: #spec.technicalEmails } + +_Appears on [`spec`](#spec)._ + +Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + +**Required** + +- [`email`](#spec.technicalEmails.email-property){: name='spec.technicalEmails.email-property'} (string, Format: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`). Email address. + ## userConfig {: #spec.userConfig } _Appears on [`spec`](#spec)._ diff --git a/docs/docs/api-reference/redis.md b/docs/docs/api-reference/redis.md index 5692f9b6..17e1667e 100644 --- a/docs/docs/api-reference/redis.md +++ b/docs/docs/api-reference/redis.md @@ -67,6 +67,7 @@ RedisSpec defines the desired state of Redis. - [`projectVpcId`](#spec.projectVpcId-property){: name='spec.projectVpcId-property'} (string, MaxLength: 36). Identifier of the VPC the service should be in, if any. - [`serviceIntegrations`](#spec.serviceIntegrations-property){: name='spec.serviceIntegrations-property'} (array of objects, Immutable, MaxItems: 1). Service integrations to specify when creating a service. Not applied after initial service creation. See below for [nested schema](#spec.serviceIntegrations). - [`tags`](#spec.tags-property){: name='spec.tags-property'} (object, AdditionalProperties: string). Tags are key-value pairs that allow you to categorize services. +- [`technicalEmails`](#spec.technicalEmails-property){: name='spec.technicalEmails-property'} (array of objects, MaxItems: 10). Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. See below for [nested schema](#spec.technicalEmails). - [`terminationProtection`](#spec.terminationProtection-property){: name='spec.terminationProtection-property'} (boolean). Prevent service from being deleted. It is recommended to have this enabled for all services. - [`userConfig`](#spec.userConfig-property){: name='spec.userConfig-property'} (object). Redis specific user configuration options. See below for [nested schema](#spec.userConfig). @@ -122,6 +123,16 @@ Service integrations to specify when creating a service. Not applied after initi - [`integrationType`](#spec.serviceIntegrations.integrationType-property){: name='spec.serviceIntegrations.integrationType-property'} (string, Enum: `read_replica`). - [`sourceServiceName`](#spec.serviceIntegrations.sourceServiceName-property){: name='spec.serviceIntegrations.sourceServiceName-property'} (string, MinLength: 1, MaxLength: 64). +## technicalEmails {: #spec.technicalEmails } + +_Appears on [`spec`](#spec)._ + +Defines the email addresses that will receive alerts about upcoming maintenance updates or warnings about service instability. + +**Required** + +- [`email`](#spec.technicalEmails.email-property){: name='spec.technicalEmails.email-property'} (string, Format: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`). Email address. + ## userConfig {: #spec.userConfig } _Appears on [`spec`](#spec)._ diff --git a/tests/mysql_test.go b/tests/mysql_test.go index 2bb6949c..5c5fbd4f 100644 --- a/tests/mysql_test.go +++ b/tests/mysql_test.go @@ -12,8 +12,8 @@ import ( mysqluserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/service/mysql" ) -func getMySQLYaml(project, name, cloudName string) string { - return fmt.Sprintf(` +func getMySQLYaml(project, name, cloudName string, includeTechnicalEmails bool) string { + baseYaml := ` apiVersion: aiven.io/v1alpha1 kind: MySQL metadata: @@ -39,8 +39,16 @@ spec: - network: 0.0.0.0/32 description: bar - network: 10.20.0.0/16 +` -`, project, name, cloudName) + if includeTechnicalEmails { + baseYaml += ` + technicalEmails: + - email: "test@example.com" +` + } + + return fmt.Sprintf(baseYaml, project, name, cloudName) } func TestMySQL(t *testing.T) { @@ -50,7 +58,7 @@ func TestMySQL(t *testing.T) { // GIVEN ctx := context.Background() name := randName("mysql") - yml := getMySQLYaml(testProject, name, testPrimaryCloudName) + yml := getMySQLYaml(testProject, name, testPrimaryCloudName, false) s := NewSession(k8sClient, avnClient, testProject) // Cleans test afterwards @@ -112,3 +120,48 @@ func TestMySQL(t *testing.T) { assert.NotEmpty(t, secret.Data["MYSQL_URI"]) assert.NotEmpty(t, secret.Data["MYSQL_REPLICA_URI"]) // business-4 has replica } + +func TestMySQLTechnicalEmails(t *testing.T) { + t.Parallel() + defer recoverPanic(t) + + // GIVEN + ctx := context.Background() + name := randName("mysql") + yml := getMySQLYaml(testProject, name, testPrimaryCloudName, true) + s := NewSession(k8sClient, avnClient, testProject) + + // Cleans test afterwards + defer s.Destroy() + + // WHEN + // Applies given manifest + require.NoError(t, s.Apply(yml)) + + // Waits kube objects + ms := new(v1alpha1.MySQL) + require.NoError(t, s.GetRunning(ms, name)) + + // THEN + // Technical emails are set + msAvn, err := avnClient.Services.Get(ctx, testProject, name) + require.NoError(t, err) + assert.Len(t, ms.Spec.TechnicalEmails, 1) + assert.Equal(t, "test@example.com", msAvn.TechnicalEmails[0].Email) + + // WHEN + // Technical emails are removed from manifest + updatedYml := getMySQLYaml(testProject, name, testPrimaryCloudName, false) + + // Applies updated manifest + require.NoError(t, s.Apply(updatedYml)) + + // Waits kube objects + require.NoError(t, s.GetRunning(ms, name)) + + // THEN + // Technical emails are removed from service + msAvnUpdated, err := avnClient.Services.Get(ctx, testProject, name) + require.NoError(t, err) + assert.Empty(t, msAvnUpdated.TechnicalEmails) +}