Skip to content

Commit

Permalink
Update Druid API for internally managed metadatastore and zookeeper (#…
Browse files Browse the repository at this point in the history
…1238)

Signed-off-by: Tapajit Chandra Paul <tapajit@appscode.com>
  • Loading branch information
tapojit047 authored Jun 28, 2024
1 parent b4f0c7a commit 735c468
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 15 deletions.
24 changes: 23 additions & 1 deletion apis/kubedb/v1alpha2/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,8 @@ const (
DatabaseReadAccess = "DatabaseReadAccess"
// user for databases that have write access
DatabaseWriteAccess = "DatabaseWriteAccess"
// check dependencies are ready
DatabaseDependencyReady = "DatabaseDependencyReady"

// Condition reasons
DataRestoreStartedByExternalInitializer = "DataRestoreStartedByExternalInitializer"
Expand All @@ -698,6 +700,7 @@ const (
DatabaseWriteAccessCheckFailed = "DatabaseWriteAccessCheckFailed"
InternalUsersCredentialSyncFailed = "InternalUsersCredentialsSyncFailed"
InternalUsersCredentialsSyncedSuccessfully = "InternalUsersCredentialsSyncedSuccessfully"
FailedToEnsureDependency = "FailedToEnsureDependency"
)

const (
Expand Down Expand Up @@ -966,7 +969,7 @@ const (
DruidExporterPort = 9104

// Common Runtime Configurations Properties
// ZooKeeperSpec
// ZooKeeper
DruidZKServiceHost = "druid.zk.service.host"
DruidZKPathsBase = "druid.zk.paths.base"
DruidZKServiceCompress = "druid.zk.service.compress"
Expand All @@ -984,6 +987,25 @@ const (
DruidMetadataStorageConnectorPasswordEnvConfig = "{\"type\": \"environment\", \"variable\": \"DRUID_METADATA_STORAGE_PASSWORD\"}"
DruidMetadataStorageCreateTables = "druid.metadata.storage.connector.createTables"

// MySQL TLS
DruidMetadataMySQLUseSSL = "druid.metadata.mysql.ssl.useSSL"
DruidMetadataMySQLClientCertKeyStoreURL = "druid.metadata.mysql.ssl.clientCertificateKeyStoreUrl"
DruidMetadataMySQLClientCertKeyStorePath = "/opt/druid/conf/tls/metadatakeystore.jks"
DruidMetadataMySQLClientCertKeyStoreType = "druid.metadata.mysql.ssl.clientCertificateKeyStoreType"
DruidMetadataMySQLClientCertKeyStoreTypeJKS = "JKS"
DruidMetadataMySQLClientCertKeyStorePassword = "druid.metadata.mysql.ssl.clientCertificateKeyStorePassword"
DruidMetadataMySQLClientCertKeyStorePasswordValue = "password"

// Postgres TLS
DruidMetadataPostgresUseSSL = "druid.metadata.postgres.ssl.useSSL"
DruidMetadataPGUseSSLMode = "druid.metadata.postgres.ssl.sslMode"
DruidMetadataPGSSLCert = "druid.metadata.postgres.ssl.sslCert"
DruidMetadataPGSSLCertPath = "/opt/druid/conf/tls/tls.crt"
DruidMetadataPGSSLKey = "druid.metadata.postgres.ssl.sslKey"
DruidMetadataPGSSLKeyPath = "/opt/druid/conf/tls/tls.key"
DruidMetadataPGSSLRootCert = "druid.metadata.postgres.ssl.sslRootCert"
DruidMetadataPGSSLRootCertPath = "/opt/druid/conf/tls/ca.cert"

// Deep Storage
DruidDeepStorageTypeKey = "druid.storage.type"
DruidDeepStorageTypeS3 = "s3"
Expand Down
103 changes: 96 additions & 7 deletions apis/kubedb/v1alpha2/druid_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
kmapi "kmodules.xyz/client-go/api/v1"
"kmodules.xyz/client-go/apiextensions"
coreutil "kmodules.xyz/client-go/core/v1"
meta_util "kmodules.xyz/client-go/meta"
Expand All @@ -45,6 +47,7 @@ import (
mona "kmodules.xyz/monitoring-agent-api/api/v1"
ofst "kmodules.xyz/offshoot-api/api/v2"
pslister "kubeops.dev/petset/client/listers/apps/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func (d *Druid) CustomResourceDefinition() *apiextensions.CustomResourceDefinition {
Expand Down Expand Up @@ -313,8 +316,10 @@ func (d *Druid) AddDruidExtensionLoadList(druidExtensionLoadList string, extensi
func (d *Druid) GetMetadataStorageType(metadataStorage string) DruidMetadataStorageType {
if metadataStorage == string(DruidMetadataStorageMySQL) || metadataStorage == strings.ToLower(string(DruidMetadataStorageMySQL)) {
return DruidMetadataStorageMySQL
} else {
} else if metadataStorage == string(DruidMetadataStoragePostgreSQL) || metadataStorage == strings.ToLower(string(DruidMetadataStoragePostgreSQL)) {
return DruidMetadataStoragePostgreSQL
} else {
panic(fmt.Sprintf("Unknown metadata storage type: %s", metadataStorage))
}
}

Expand Down Expand Up @@ -441,7 +446,7 @@ func (d *Druid) SetDefaults() {
d.Spec.Topology.MiddleManagers.StorageType = StorageTypeDurable
}
if d.Spec.Topology.MiddleManagers.Storage == nil && d.Spec.Topology.MiddleManagers.StorageType == StorageTypeDurable {
d.Spec.Topology.MiddleManagers.Storage = d.getDefaultPVC()
d.Spec.Topology.MiddleManagers.Storage = d.GetDefaultPVC()
}
if version.Major() > 25 {
if d.Spec.Topology.MiddleManagers.PodTemplate.Spec.SecurityContext == nil {
Expand All @@ -463,7 +468,7 @@ func (d *Druid) SetDefaults() {
d.Spec.Topology.Historicals.StorageType = StorageTypeDurable
}
if d.Spec.Topology.Historicals.Storage == nil && d.Spec.Topology.Historicals.StorageType == StorageTypeDurable {
d.Spec.Topology.Historicals.Storage = d.getDefaultPVC()
d.Spec.Topology.Historicals.Storage = d.GetDefaultPVC()
}
if version.Major() > 25 {
if d.Spec.Topology.Historicals.PodTemplate.Spec.SecurityContext == nil {
Expand Down Expand Up @@ -504,11 +509,65 @@ func (d *Druid) SetDefaults() {
}
}
}
if d.Spec.MetadataStorage != nil {
if d.Spec.MetadataStorage.Name != "" && d.Spec.MetadataStorage.Namespace == "" {
d.Spec.MetadataStorage.Namespace = d.Namespace

if d.Spec.MetadataStorage == nil {
d.Spec.MetadataStorage = &MetadataStorage{}
}
if d.Spec.MetadataStorage.Namespace == "" {
d.Spec.MetadataStorage.Namespace = d.Namespace
}
if d.Spec.MetadataStorage.LinkedDB == "" {
d.Spec.MetadataStorage.LinkedDB = "druid"
}
if d.Spec.MetadataStorage.CreateTables == nil {
d.Spec.MetadataStorage.CreateTables = ptr.To(true)
}

if d.Spec.MetadataStorage.Type == "" {
if d.Spec.MetadataStorage.ExternallyManaged {
appBinding, err := d.GetAppBinding(d.Spec.MetadataStorage.Name, d.Spec.MetadataStorage.Namespace)
if err != nil {
return
}
d.Spec.MetadataStorage.Type = d.GetMetadataStorageType(appBinding.Spec.AppRef.Kind)
} else {
d.Spec.MetadataStorage.Type = DruidMetadataStorageMySQL
}
}
if !d.Spec.MetadataStorage.ExternallyManaged {
if d.Spec.MetadataStorage.ObjectReference == nil {
d.Spec.MetadataStorage.ObjectReference = &kmapi.ObjectReference{}
}
d.Spec.MetadataStorage.Name = d.GetMetadataStorageName()
}

if d.Spec.MetadataStorage.Version == nil {
var defaultVersion string
if d.Spec.MetadataStorage.Type == DruidMetadataStorageMySQL {
defaultVersion = "8.0.35"
} else {
defaultVersion = "13.13"
}
d.Spec.MetadataStorage.Version = &defaultVersion
}

if d.Spec.ZookeeperRef == nil {
d.Spec.ZookeeperRef = &ZookeeperRef{}
}
if !d.Spec.ZookeeperRef.ExternallyManaged {
if d.Spec.ZookeeperRef.ObjectReference == nil {
d.Spec.ZookeeperRef.ObjectReference = &kmapi.ObjectReference{}
}
if d.Spec.ZookeeperRef.Name == "" {
d.Spec.ZookeeperRef.Name = d.GetZooKeeperName()
}
if d.Spec.ZookeeperRef.Namespace == "" {
d.Spec.ZookeeperRef.Namespace = d.Namespace
}
defaultVersion := "3.7.2"
d.Spec.ZookeeperRef.Version = &defaultVersion
}

if d.Spec.Monitor != nil {
if d.Spec.Monitor.Prometheus == nil {
d.Spec.Monitor.Prometheus = &mona.PrometheusSpec{}
Expand All @@ -520,8 +579,11 @@ func (d *Druid) SetDefaults() {
}
}

func (d *Druid) getDefaultPVC() *core.PersistentVolumeClaimSpec {
func (d *Druid) GetDefaultPVC() *core.PersistentVolumeClaimSpec {
return &core.PersistentVolumeClaimSpec{
AccessModes: []core.PersistentVolumeAccessMode{
core.ReadWriteOnce,
},
Resources: core.VolumeResourceRequirements{
Requests: core.ResourceList{
core.ResourceStorage: resource.MustParse("1Gi"),
Expand Down Expand Up @@ -618,3 +680,30 @@ func (d *Druid) ReplicasAreReady(lister pslister.PetSetLister) (bool, string, er
}
return checkReplicasOfPetSet(lister.PetSets(d.Namespace), labels.SelectorFromSet(d.OffshootLabels()), expectedItems)
}

func (d *Druid) GetAppBinding(name string, namespace string) (*appcat.AppBinding, error) {
appbinding := &appcat.AppBinding{}
appbinding.Namespace = namespace
appbinding.Name = name

if err := DefaultClient.Get(context.TODO(), client.ObjectKeyFromObject(appbinding), appbinding); err != nil {
klog.Error(err, fmt.Sprintf("failed to get appbinding for metadata storage %s/%s", name, namespace))
return nil, err
}
return appbinding, nil
}

func (d *Druid) GetMetadataStorageName() string {
if d.Spec.MetadataStorage.Type == DruidMetadataStoragePostgreSQL {
return d.OffShootName() + "-pg-metadata"
}
return d.OffShootName() + "-mysql-metadata"
}

func (d *Druid) GetZooKeeperName() string {
return d.OffShootName() + "-zk"
}

func (d *Druid) GetInitConfigMapName() string {
return d.OffShootName() + "-init-script"
}
24 changes: 21 additions & 3 deletions apis/kubedb/v1alpha2/druid_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ type DruidSpec struct {
//TLS *kmapi.TLSConfig `json:"tls,omitempty"`

// MetadataStorage contains information for Druid to connect to external dependency metadata storage
MetadataStorage *MetadataStorage `json:"metadataStorage"`
// +optional
MetadataStorage *MetadataStorage `json:"metadataStorage,omitempty"`

// DeepStorage contains specification for druid to connect to the deep storage
DeepStorage *DeepStorageSpec `json:"deepStorage"`
Expand Down Expand Up @@ -156,7 +157,7 @@ type DruidDataNode struct {
}

type MetadataStorage struct {
// Name of the appbinding of zookeeper
// Name and namespace of the appbinding of metadata storage
// +optional
*kmapi.ObjectReference `json:",omitempty"`

Expand All @@ -167,6 +168,16 @@ type MetadataStorage struct {
// If Druid has the permission to create new tables
// +optional
CreateTables *bool `json:"createTables,omitempty"`

// +optional
LinkedDB string `json:"linkedDB,omitempty"`

// +optional
ExternallyManaged bool `json:"externallyManaged,omitempty"`

// Version of the MySQL/PG used
// +optional
Version *string `json:"version,omitempty"`
}

type DeepStorageSpec struct {
Expand All @@ -181,13 +192,20 @@ type DeepStorageSpec struct {
}

type ZookeeperRef struct {
// Name of the appbinding of zookeeper
// Name and namespace of appbinding of zookeeper
// +optional
*kmapi.ObjectReference `json:",omitempty"`

// Base ZooKeeperSpec path
// +optional
PathsBase string `json:"pathsBase,omitempty"`

// +optional
ExternallyManaged bool `json:"externallyManaged,omitempty"`

// Version of the ZK used
// +optional
Version *string `json:"version,omitempty"`
}

// DruidStatus defines the observed state of Druid
Expand Down
4 changes: 2 additions & 2 deletions apis/kubedb/v1alpha2/druid_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ func (d *Druid) validateCreateOrUpdate() field.ErrorList {
d.Name,
"spec.metadataStorage is missing"))
} else {
if d.Spec.MetadataStorage.Name == "" && d.Spec.MetadataStorage.Type == "" {
if d.Spec.MetadataStorage.ExternallyManaged && d.Spec.MetadataStorage.Name == "" {
allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("metadataStorage").Child("name"),
d.Name,
"spec.metadataStorage.type and spec.metadataStorage.name both can not be empty simultaneously"))
"spec.metadataStorage.name can not be empty when d.Spec.MetadataStorage.ExternallyManaged is true"))
}
}

Expand Down
34 changes: 33 additions & 1 deletion apis/kubedb/v1alpha2/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions apis/kubedb/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 735c468

Please sign in to comment.