Skip to content

Commit

Permalink
feat(serviceintegrationendpoint): add kind (#721)
Browse files Browse the repository at this point in the history
  • Loading branch information
byashimov authored May 2, 2024
1 parent e99ec55 commit 662ecf1
Show file tree
Hide file tree
Showing 28 changed files with 2,540 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [MAJOR.MINOR.PATCH] - YYYY-MM-DD

- Add kind: `ServiceIntegrationEndpoint`
- Change `Kafka` field `userConfig.kafka_version`: enum ~~`[3.4, 3.5, 3.6]`~~`[3.4, 3.5, 3.6, 3.7]`

## v0.19.0 - 2024-04-18
Expand Down
12 changes: 12 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,16 @@ resources:
kind: ClickhouseRole
path: github.com/aiven/aiven-operator/api/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: aiven.io
kind: ServiceIntegrationEndpoint
path: github.com/aiven/aiven-operator/api/v1alpha1
version: v1alpha1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
version: "3"
12 changes: 10 additions & 2 deletions api/v1alpha1/serviceintegration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ func (in *ServiceIntegration) Conditions() *[]metav1.Condition {
return &in.Status.Conditions
}

func (in *ServiceIntegration) GetUserConfig() (any, error) {
configs := map[string]any{
func (in *ServiceIntegration) getUserConfigFields() map[string]any {
return map[string]any{
"clickhouse_kafka": in.Spec.ClickhouseKafkaUserConfig,
"clickhouse_postgresql": in.Spec.ClickhousePostgreSQLUserConfig,
"datadog": in.Spec.DatadogUserConfig,
Expand All @@ -139,7 +139,15 @@ func (in *ServiceIntegration) GetUserConfig() (any, error) {
"logs": in.Spec.LogsUserConfig,
"metrics": in.Spec.MetricsUserConfig,
}
}

func (in *ServiceIntegration) HasUserConfig() bool {
_, ok := in.getUserConfigFields()[in.Spec.IntegrationType]
return ok
}

func (in *ServiceIntegration) GetUserConfig() (any, error) {
configs := in.getUserConfigFields()
thisType := in.Spec.IntegrationType

// Checks if it is the only configuration set
Expand Down
167 changes: 167 additions & 0 deletions api/v1alpha1/serviceintegrationendpoint_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright (c) 2024 Aiven, Helsinki, Finland. https://aiven.io/

package v1alpha1

import (
"fmt"
"reflect"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

datadoguserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/datadog"
externalawscloudwatchlogsuserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/external_aws_cloudwatch_logs"
externalawscloudwatchmetricsuserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/external_aws_cloudwatch_metrics"
externalelasticsearchlogsuserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/external_elasticsearch_logs"
externalgooglecloudbigqueryuserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/external_google_cloud_bigquery"
externalgooglecloudlogginguserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/external_google_cloud_logging"
externalkafkauserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/external_kafka"
externalopensearchlogsuserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/external_opensearch_logs"
externalpostgresqluserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/external_postgresql"
externalschemaregistryuserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/external_schema_registry"
jolokiauserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/jolokia"
prometheususerconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/prometheus"
rsysloguserconfig "github.com/aiven/aiven-operator/api/v1alpha1/userconfig/integrationendpoints/rsyslog"
)

// ServiceIntegrationEndpointSpec defines the desired state of ServiceIntegrationEndpoint
type ServiceIntegrationEndpointSpec struct {
ProjectDependant `json:",inline"`

// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
// +kubebuilder:validation:Enum=autoscaler;datadog;external_aws_cloudwatch_logs;external_aws_cloudwatch_metrics;external_aws_s3;external_clickhouse;external_elasticsearch_logs;external_google_cloud_bigquery;external_google_cloud_logging;external_kafka;external_mysql;external_opensearch_logs;external_postgresql;external_redis;external_schema_registry;jolokia;prometheus;rsyslog
// Type of the service integration endpoint
EndpointType string `json:"endpointType"`

// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
// +kubebuilder:validation:MaxLength=36
// Source endpoint for the integration (if any)
EndpointName string `json:"endpointName,omitempty"`

// Datadog configuration values
Datadog *datadoguserconfig.DatadogUserConfig `json:"datadog,omitempty"`

// ExternalAwsCloudwatchLogs configuration values
ExternalAwsCloudwatchLogs *externalawscloudwatchlogsuserconfig.ExternalAwsCloudwatchLogsUserConfig `json:"externalAWSCloudwatchLogs,omitempty"`

// ExternalAwsCloudwatchMetrics configuration values
ExternalAwsCloudwatchMetrics *externalawscloudwatchmetricsuserconfig.ExternalAwsCloudwatchMetricsUserConfig `json:"externalAWSCloudwatchMetrics,omitempty"`

// ExternalElasticsearchLogs configuration values
ExternalElasticsearchLogs *externalelasticsearchlogsuserconfig.ExternalElasticsearchLogsUserConfig `json:"externalElasticsearchLogs,omitempty"`

// ExternalGoogleCloudBigquery configuration values
ExternalGoogleCloudBigquery *externalgooglecloudbigqueryuserconfig.ExternalGoogleCloudBigqueryUserConfig `json:"externalGoogleCloudBigquery,omitempty"`

// ExternalGoogleCloudLogging configuration values
ExternalGoogleCloudLogging *externalgooglecloudlogginguserconfig.ExternalGoogleCloudLoggingUserConfig `json:"externalGoogleCloudLogging,omitempty"`

// ExternalKafka configuration values
ExternalKafka *externalkafkauserconfig.ExternalKafkaUserConfig `json:"externalKafka,omitempty"`

// ExternalOpensearchLogs configuration values
ExternalOpensearchLogs *externalopensearchlogsuserconfig.ExternalOpensearchLogsUserConfig `json:"externalOpensearchLogs,omitempty"`

// ExternalPostgresql configuration values
ExternalPostgresql *externalpostgresqluserconfig.ExternalPostgresqlUserConfig `json:"externalPostgresql,omitempty"`

// ExternalSchemaRegistry configuration values
ExternalSchemaRegistry *externalschemaregistryuserconfig.ExternalSchemaRegistryUserConfig `json:"externalSchemaRegistry,omitempty"`

// Jolokia configuration values
Jolokia *jolokiauserconfig.JolokiaUserConfig `json:"jolokia,omitempty"`

// Prometheus configuration values
Prometheus *prometheususerconfig.PrometheusUserConfig `json:"prometheus,omitempty"`

// Rsyslog configuration values
Rsyslog *rsysloguserconfig.RsyslogUserConfig `json:"rsyslog,omitempty"`
}

// ServiceIntegrationEndpointStatus defines the observed state of ServiceIntegrationEndpoint
type ServiceIntegrationEndpointStatus struct {
// Conditions represent the latest available observations of an ServiceIntegrationEndpoint state
Conditions []metav1.Condition `json:"conditions"`

// Service integration ID
ID string `json:"id"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// ServiceIntegrationEndpoint is the Schema for the serviceintegrationendpoints API
// +kubebuilder:printcolumn:name="Project",type="string",JSONPath=".spec.project"
// +kubebuilder:printcolumn:name="Endpoint Name",type="string",JSONPath=".spec.endpointName"
// +kubebuilder:printcolumn:name="Endpoint Type",type="string",JSONPath=".spec.endpointType"
// +kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.id"
type ServiceIntegrationEndpoint struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ServiceIntegrationEndpointSpec `json:"spec,omitempty"`
Status ServiceIntegrationEndpointStatus `json:"status,omitempty"`
}

var _ AivenManagedObject = &ServiceIntegrationEndpoint{}

func (*ServiceIntegrationEndpoint) NoSecret() bool {
return true
}

func (in *ServiceIntegrationEndpoint) AuthSecretRef() *AuthSecretReference {
return in.Spec.AuthSecretRef
}

func (in *ServiceIntegrationEndpoint) Conditions() *[]metav1.Condition {
return &in.Status.Conditions
}

func (in *ServiceIntegrationEndpoint) getUserConfigFields() map[string]any {
return map[string]any{
"datadog": in.Spec.Datadog,
"external_aws_cloudwatch_logs": in.Spec.ExternalAwsCloudwatchLogs,
"external_aws_cloudwatch_metrics": in.Spec.ExternalAwsCloudwatchMetrics,
"external_elasticsearch_logs": in.Spec.ExternalElasticsearchLogs,
"external_google_cloud_bigquery": in.Spec.ExternalGoogleCloudBigquery,
"external_google_cloud_logging": in.Spec.ExternalGoogleCloudLogging,
"external_kafka": in.Spec.ExternalKafka,
"external_opensearch_logs": in.Spec.ExternalOpensearchLogs,
"external_postgresql": in.Spec.ExternalPostgresql,
"external_schema_registry": in.Spec.ExternalSchemaRegistry,
"jolokia": in.Spec.Jolokia,
"prometheus": in.Spec.Prometheus,
"rsyslog": in.Spec.Rsyslog,
}
}

func (in *ServiceIntegrationEndpoint) HasUserConfig() bool {
_, ok := in.getUserConfigFields()[in.Spec.EndpointType]
return ok
}

func (in *ServiceIntegrationEndpoint) GetUserConfig() (any, error) {
configs := in.getUserConfigFields()
thisType := in.Spec.EndpointType

// Checks if it is the only configuration set
for k, v := range configs {
if k != thisType && !reflect.ValueOf(v).IsNil() {
return nil, fmt.Errorf("got additional configuration for integration endpoint type %q", k)
}
}

return configs[thisType], nil
}

// +kubebuilder:object:root=true

// ServiceIntegrationEndpointList contains a list of ServiceIntegrationEndpoint
type ServiceIntegrationEndpointList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ServiceIntegrationEndpoint `json:"items"`
}

func init() {
SchemeBuilder.Register(&ServiceIntegrationEndpoint{}, &ServiceIntegrationEndpointList{})
}
57 changes: 57 additions & 0 deletions api/v1alpha1/serviceintegrationendpoint_webhook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) 2024 Aiven, Helsinki, Finland. https://aiven.io/

package v1alpha1

import (
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)

// log is for logging in this package.
var serviceintegrationendpointlog = logf.Log.WithName("serviceintegrationendpoint-resource")

func (in *ServiceIntegrationEndpoint) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(in).
Complete()
}

//+kubebuilder:webhook:path=/mutate-aiven-io-v1alpha1-serviceintegrationendpoint,mutating=true,failurePolicy=fail,groups=aiven.io,resources=serviceintegrationendpoints,verbs=create;update,versions=v1alpha1,name=mserviceintegrationendpoint.kb.io,sideEffects=none,admissionReviewVersions=v1

var _ webhook.Defaulter = &ServiceIntegrationEndpoint{}

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (in *ServiceIntegrationEndpoint) Default() {
serviceintegrationendpointlog.Info("default", "name", in.Name)
}

//+kubebuilder:webhook:verbs=create;update,path=/validate-aiven-io-v1alpha1-serviceintegrationendpoint,mutating=false,failurePolicy=fail,groups=aiven.io,resources=serviceintegrationendpoints,versions=v1alpha1,name=vserviceintegrationendpoint.kb.io,sideEffects=none,admissionReviewVersions=v1

var _ webhook.Validator = &ServiceIntegrationEndpoint{}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (in *ServiceIntegrationEndpoint) ValidateCreate() error {
serviceintegrationendpointlog.Info("validate create", "name", in.Name)

// We need the validation here only
_, err := in.GetUserConfig()
return err
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (in *ServiceIntegrationEndpoint) ValidateUpdate(old runtime.Object) error {
serviceintegrationendpointlog.Info("validate update", "name", in.Name)

// We need the validation here only
_, err := in.GetUserConfig()
return err
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (in *ServiceIntegrationEndpoint) ValidateDelete() error {
serviceintegrationendpointlog.Info("validate delete", "name", in.Name)

return nil
}
3 changes: 3 additions & 0 deletions api/v1alpha1/setup_webhooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ func SetupWebhooks(mgr ctrl.Manager) error {
if err := (&ServiceIntegration{}).SetupWebhookWithManager(mgr); err != nil {
return fmt.Errorf("webhook ServiceIntegration: %w", err)
}
if err := (&ServiceIntegrationEndpoint{}).SetupWebhookWithManager(mgr); err != nil {
return fmt.Errorf("webhook ServiceIntegrationEndpoint: %w", err)
}
if err := (&KafkaConnector{}).SetupWebhookWithManager(mgr); err != nil {
return fmt.Errorf("webhook KafkaConnector: %w", err)
}
Expand Down
Loading

0 comments on commit 662ecf1

Please sign in to comment.