diff --git a/apis/kubedb/v1alpha2/druid_helpers.go b/apis/kubedb/v1alpha2/druid_helpers.go index e03d54ea9d..73e66f4d2f 100644 --- a/apis/kubedb/v1alpha2/druid_helpers.go +++ b/apis/kubedb/v1alpha2/druid_helpers.go @@ -179,28 +179,40 @@ func (d *Druid) PetSetName(nodeRole DruidNodeRoleType) string { } func (d *Druid) PodLabels(nodeType DruidNodeRoleType, extraLabels ...map[string]string) map[string]string { - nodeSpec := d.GetNodeSpec(nodeType) - return d.offShootLabels(meta_util.OverwriteKeys(d.OffShootSelectors(), extraLabels...), nodeSpec.PodTemplate.Labels) + nodeSpec, dataNodeSpec := d.GetNodeSpec(nodeType) + var labels map[string]string + if nodeSpec != nil { + labels = nodeSpec.PodTemplate.Labels + } else { + labels = dataNodeSpec.PodTemplate.Labels + } + return d.offShootLabels(meta_util.OverwriteKeys(d.OffShootSelectors(), extraLabels...), labels) } func (d *Druid) PodControllerLabels(nodeType DruidNodeRoleType, extraLabels ...map[string]string) map[string]string { - nodeSpec := d.GetNodeSpec(nodeType) - return d.offShootLabels(meta_util.OverwriteKeys(d.OffShootSelectors(), extraLabels...), nodeSpec.PodTemplate.Controller.Labels) + nodeSpec, dataNodeSpec := d.GetNodeSpec(nodeType) + var labels map[string]string + if nodeSpec != nil { + labels = nodeSpec.PodTemplate.Controller.Labels + } else { + labels = dataNodeSpec.PodTemplate.Controller.Labels + } + return d.offShootLabels(meta_util.OverwriteKeys(d.OffShootSelectors(), extraLabels...), labels) } -func (d *Druid) GetNodeSpec(nodeType DruidNodeRoleType) *DruidNode { +func (d *Druid) GetNodeSpec(nodeType DruidNodeRoleType) (*DruidNode, *DruidDataNode) { if nodeType == DruidNodeRoleCoordinators { - return d.Spec.Topology.Coordinators + return d.Spec.Topology.Coordinators, nil } else if nodeType == DruidNodeRoleOverlords { - return d.Spec.Topology.Overlords + return d.Spec.Topology.Overlords, nil } else if nodeType == DruidNodeRoleMiddleManagers { - return d.Spec.Topology.MiddleManagers + return nil, d.Spec.Topology.MiddleManagers } else if nodeType == DruidNodeRoleHistoricals { - return d.Spec.Topology.Historicals + return nil, d.Spec.Topology.Historicals } else if nodeType == DruidNodeRoleBrokers { - return d.Spec.Topology.Brokers + return d.Spec.Topology.Brokers, nil } else if nodeType == DruidNodeRoleRouters { - return d.Spec.Topology.Routers + return d.Spec.Topology.Routers, nil } panic("Node role name does not match any known types") @@ -361,10 +373,6 @@ func (d *Druid) SetDefaults() { d.Spec.TerminationPolicy = TerminationPolicyDelete } - if d.Spec.StorageType == "" { - d.Spec.StorageType = StorageTypeDurable - } - if d.Spec.DisableSecurity == nil { d.Spec.DisableSecurity = pointer.BoolP(false) } @@ -397,6 +405,9 @@ func (d *Druid) SetDefaults() { d.Spec.Topology.Coordinators = &DruidNode{} } if d.Spec.Topology.Coordinators != nil { + if d.Spec.Topology.Coordinators.Replicas == nil { + d.Spec.Topology.Coordinators.Replicas = pointer.Int32P(1) + } if version.Major() > 25 { if d.Spec.Topology.Coordinators.PodTemplate.Spec.SecurityContext == nil { d.Spec.Topology.Coordinators.PodTemplate.Spec.SecurityContext = &v1.PodSecurityContext{FSGroup: druidVersion.Spec.SecurityContext.RunAsUser} @@ -405,7 +416,11 @@ func (d *Druid) SetDefaults() { d.setDefaultContainerResourceLimits(&d.Spec.Topology.Coordinators.PodTemplate, DruidNodeRoleCoordinators) } } + if d.Spec.Topology.Overlords != nil { + if d.Spec.Topology.Overlords.Replicas == nil { + d.Spec.Topology.Overlords.Replicas = pointer.Int32P(1) + } if version.Major() > 25 { if d.Spec.Topology.Overlords.PodTemplate.Spec.SecurityContext == nil { d.Spec.Topology.Overlords.PodTemplate.Spec.SecurityContext = &v1.PodSecurityContext{FSGroup: druidVersion.Spec.SecurityContext.RunAsUser} @@ -416,12 +431,18 @@ func (d *Druid) SetDefaults() { } if d.Spec.Topology.MiddleManagers == nil { - d.Spec.Topology.MiddleManagers = &DruidNode{} - } - if d.Spec.Topology.MiddleManagers.Storage == nil && d.Spec.StorageType == StorageTypeDurable { - d.Spec.Topology.MiddleManagers.Storage = d.getDefaultPVC() + d.Spec.Topology.MiddleManagers = &DruidDataNode{} } if d.Spec.Topology.MiddleManagers != nil { + if d.Spec.Topology.MiddleManagers.Replicas == nil { + d.Spec.Topology.MiddleManagers.Replicas = pointer.Int32P(1) + } + if d.Spec.Topology.MiddleManagers.StorageType == "" { + 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() + } if version.Major() > 25 { if d.Spec.Topology.MiddleManagers.PodTemplate.Spec.SecurityContext == nil { d.Spec.Topology.MiddleManagers.PodTemplate.Spec.SecurityContext = &v1.PodSecurityContext{FSGroup: druidVersion.Spec.SecurityContext.RunAsUser} @@ -432,12 +453,18 @@ func (d *Druid) SetDefaults() { } if d.Spec.Topology.Historicals == nil { - d.Spec.Topology.Historicals = &DruidNode{} - } - if d.Spec.Topology.Historicals.Storage == nil && d.Spec.StorageType == StorageTypeDurable { - d.Spec.Topology.Historicals.Storage = d.getDefaultPVC() + d.Spec.Topology.Historicals = &DruidDataNode{} } if d.Spec.Topology.Historicals != nil { + if d.Spec.Topology.Historicals.Replicas == nil { + d.Spec.Topology.Historicals.Replicas = pointer.Int32P(1) + } + if d.Spec.Topology.Historicals.StorageType == "" { + 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() + } if version.Major() > 25 { if d.Spec.Topology.Historicals.PodTemplate.Spec.SecurityContext == nil { d.Spec.Topology.Historicals.PodTemplate.Spec.SecurityContext = &v1.PodSecurityContext{FSGroup: druidVersion.Spec.SecurityContext.RunAsUser} @@ -451,6 +478,9 @@ func (d *Druid) SetDefaults() { d.Spec.Topology.Brokers = &DruidNode{} } if d.Spec.Topology.Brokers != nil { + if d.Spec.Topology.Brokers.Replicas == nil { + d.Spec.Topology.Brokers.Replicas = pointer.Int32P(1) + } if version.Major() > 25 { if d.Spec.Topology.Brokers.PodTemplate.Spec.SecurityContext == nil { d.Spec.Topology.Brokers.PodTemplate.Spec.SecurityContext = &v1.PodSecurityContext{FSGroup: druidVersion.Spec.SecurityContext.RunAsUser} @@ -462,6 +492,9 @@ func (d *Druid) SetDefaults() { } if d.Spec.Topology.Routers != nil { + if d.Spec.Topology.Routers.Replicas == nil { + d.Spec.Topology.Routers.Replicas = pointer.Int32P(1) + } if version.Major() > 25 { if d.Spec.Topology.Routers.PodTemplate.Spec.SecurityContext == nil { d.Spec.Topology.Routers.PodTemplate.Spec.SecurityContext = &v1.PodSecurityContext{FSGroup: druidVersion.Spec.SecurityContext.RunAsUser} diff --git a/apis/kubedb/v1alpha2/druid_types.go b/apis/kubedb/v1alpha2/druid_types.go index 3d9bc7976f..1ec93318f3 100644 --- a/apis/kubedb/v1alpha2/druid_types.go +++ b/apis/kubedb/v1alpha2/druid_types.go @@ -64,9 +64,6 @@ type DruidSpec struct { // +optional Topology *DruidClusterTopology `json:"topology,omitempty"` - // StorageType can be durable (default) or ephemeral. - StorageType StorageType `json:"storageType,omitempty"` - // disable security. It disables authentication security of user. // If unset, default is false // +optional @@ -122,9 +119,9 @@ type DruidClusterTopology struct { // +optional Overlords *DruidNode `json:"overlords,omitempty"` - MiddleManagers *DruidNode `json:"middleManagers,omitempty"` + MiddleManagers *DruidDataNode `json:"middleManagers,omitempty"` - Historicals *DruidNode `json:"historicals,omitempty"` + Historicals *DruidDataNode `json:"historicals,omitempty"` Brokers *DruidNode `json:"brokers,omitempty"` // +optional @@ -141,10 +138,6 @@ type DruidNode struct { // +optional Suffix string `json:"suffix,omitempty"` - // Storage to specify how storage shall be used. - // +optional - Storage *core.PersistentVolumeClaimSpec `json:"storage,omitempty"` - // PodTemplate is an optional configuration for pods used to expose database // +optional PodTemplate ofst.PodTemplateSpec `json:"podTemplate,omitempty"` @@ -163,6 +156,18 @@ type DruidNode struct { // +kubebuilder:default={name: "default"} // +optional PodPlacementPolicy *core.LocalObjectReference `json:"podPlacementPolicy,omitempty"` +} + +type DruidDataNode struct { + // DruidDataNode has all the characteristics of DruidNode + DruidNode `json:",inline"` + + // StorageType specifies if the storage + // of this node is durable (default) or ephemeral. + StorageType StorageType `json:"storageType,omitempty"` + + // Storage to specify how storage shall be used. + Storage *core.PersistentVolumeClaimSpec `json:"storage,omitempty"` // EphemeralStorage spec to specify the configuration of ephemeral storage type. EphemeralStorage *core.EmptyDirVolumeSource `json:"ephemeralStorage,omitempty"` diff --git a/apis/kubedb/v1alpha2/druid_webhook.go b/apis/kubedb/v1alpha2/druid_webhook.go index 4e43758ed1..0fa87d6ad0 100644 --- a/apis/kubedb/v1alpha2/druid_webhook.go +++ b/apis/kubedb/v1alpha2/druid_webhook.go @@ -19,6 +19,7 @@ package v1alpha2 import ( "context" "errors" + "fmt" catalog "kubedb.dev/apimachinery/apis/catalog/v1alpha1" @@ -112,18 +113,6 @@ func (d *Druid) validateCreateOrUpdate() field.ErrorList { } } - if d.Spec.StorageType == "" { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("storageType"), - d.Name, - "StorageType can not be empty")) - } else { - if d.Spec.StorageType != StorageTypeDurable && d.Spec.StorageType != StorageTypeEphemeral { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("storageType"), - d.Name, - "StorageType should be either durable or ephemeral")) - } - } - if d.Spec.DeepStorage == nil { allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("deepStorage"), d.Name, @@ -153,184 +142,120 @@ func (d *Druid) validateCreateOrUpdate() field.ErrorList { d.Name, "spec.topology can not be empty")) } else { + // Required Nodes if d.Spec.Topology.Coordinators == nil { allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("coordinators"), d.Name, "spec.topology.coordinators can not be empty")) } else { + validateDruidNode(d.Name, d.Spec.Topology.Coordinators, DruidNodeRoleCoordinators, &allErr) + } - if *d.Spec.Topology.Coordinators.Replicas <= 0 { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("coordinators").Child("replicas"), - d.Name, - "number of replicas can not be 0 or less")) - } + if d.Spec.Topology.Brokers == nil { + allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("brokers").Child("replicas"), + d.Name, + "spec.topology.brokers.replicas can not be empty")) + } else { + validateDruidNode(d.Name, d.Spec.Topology.Coordinators, DruidNodeRoleBrokers, &allErr) + } - err := druidValidateVolumes(&d.Spec.Topology.Coordinators.PodTemplate, DruidNodeRoleCoordinators) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("coordinators").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } - err = druidValidateVolumesMountPaths(&d.Spec.Topology.Coordinators.PodTemplate, DruidNodeRoleCoordinators) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("coordinators").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } + // Optional Nodes + if d.Spec.Topology.Overlords != nil { + validateDruidNode(d.Name, d.Spec.Topology.Coordinators, DruidNodeRoleOverlords, &allErr) + } + if d.Spec.Topology.Routers != nil { + validateDruidNode(d.Name, d.Spec.Topology.Coordinators, DruidNodeRoleRouters, &allErr) } + // Data Nodes if d.Spec.Topology.MiddleManagers == nil { allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("middleManagers"), d.Name, "spec.topology.middleManagers can not be empty")) } else { - if *d.Spec.Topology.MiddleManagers.Replicas <= 0 { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("middleManagers").Child("replicas"), - d.Name, - "number of replicas can not be 0 or less")) - } - - if d.Spec.StorageType == StorageTypeEphemeral && d.Spec.Topology.MiddleManagers.Storage != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("middleManagers").Child("storage"), - d.Name, - "spec.topology.middleManagers.storage can not be set when storageType is Ephemeral")) - } - if d.Spec.StorageType == StorageTypeDurable && d.Spec.Topology.MiddleManagers.EphemeralStorage != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("middleManagers").Child("ephemeralStorage"), - d.Name, - "spec.topology.middleManagers.ephemeralStorage can not be set when storageType is Durable")) - } - if d.Spec.StorageType == StorageTypeDurable && d.Spec.Topology.MiddleManagers.Storage == nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("middleManagers").Child("storage"), - d.Name, - "spec.topology.middleManagers.storage needs to be set when storageType is Durable")) - } - - err := druidValidateVolumes(&d.Spec.Topology.MiddleManagers.PodTemplate, DruidNodeRoleMiddleManagers) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("middleManagers").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } - err = druidValidateVolumesMountPaths(&d.Spec.Topology.MiddleManagers.PodTemplate, DruidNodeRoleMiddleManagers) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("middleManagers").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } + validateDruidDataNode(d.Name, d.Spec.Topology.MiddleManagers, DruidNodeRoleMiddleManagers, &allErr) } - if d.Spec.Topology.Historicals == nil { allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("historicals"), d.Name, "spec.topology.historicals can not be empty")) } else { - if *d.Spec.Topology.Historicals.Replicas <= 0 { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("historicals").Child("replicas"), - d.Name, - "number of replicas can not be 0 or less")) - } - - if d.Spec.StorageType == StorageTypeEphemeral && d.Spec.Topology.Historicals.Storage != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("historicals").Child("storage"), - d.Name, - "spec.topology.historicals.storage can not be set when storageType is Ephemeral")) - } - if d.Spec.StorageType == StorageTypeDurable && d.Spec.Topology.Historicals.EphemeralStorage != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("historicals").Child("ephemeralStorage"), - d.Name, - "spec.topology.historicals.ephemeralStorage can not be set when storageType is Durable")) - } - if d.Spec.StorageType == StorageTypeDurable && d.Spec.Topology.Historicals.Storage == nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("historicals").Child("storage"), - d.Name, - "spec.topology.historicals.storage needs to be set when storageType is Durable")) - } - - err := druidValidateVolumes(&d.Spec.Topology.Historicals.PodTemplate, DruidNodeRoleHistoricals) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("historicals").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } - err = druidValidateVolumesMountPaths(&d.Spec.Topology.Historicals.PodTemplate, DruidNodeRoleHistoricals) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("historicals").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } + validateDruidDataNode(d.Name, d.Spec.Topology.Historicals, DruidNodeRoleHistoricals, &allErr) } + } + if len(allErr) == 0 { + return nil + } + return allErr +} - if d.Spec.Topology.Brokers == nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("brokers").Child("replicas"), - d.Name, - "spec.topology.brokers.replicas can not be empty")) - } else { - if *d.Spec.Topology.Brokers.Replicas <= 0 { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("brokers").Child("replicas"), - d.Name, - "number of replicas can not be 0 or less")) - } +func validateDruidNode(dbName string, node *DruidNode, nodeType DruidNodeRoleType, allErr *field.ErrorList) { + if *node.Replicas <= 0 { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("replicas"), + dbName, + "number of replicas can not be 0 or less")) + } - err := druidValidateVolumes(&d.Spec.Topology.Brokers.PodTemplate, DruidNodeRoleBrokers) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("brokers").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } - err = druidValidateVolumesMountPaths(&d.Spec.Topology.Brokers.PodTemplate, DruidNodeRoleBrokers) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("brokers").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } - } + err := druidValidateVolumes(&node.PodTemplate, nodeType) + if err != nil { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("podTemplate").Child("spec").Child("volumes"), + dbName, + err.Error())) + } + err = druidValidateVolumesMountPaths(&node.PodTemplate, nodeType) + if err != nil { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("podTemplate").Child("spec").Child("volumes"), + dbName, + err.Error())) + } +} - if d.Spec.Topology.Overlords != nil { - if *d.Spec.Topology.Overlords.Replicas <= 0 { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("overlords").Child("replicas"), - d.Name, - "number of replicas can not be 0 or less")) - } +func validateDruidDataNode(dbName string, node *DruidDataNode, nodeType DruidNodeRoleType, allErr *field.ErrorList) { + if *node.Replicas <= 0 { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("replicas"), + dbName, + fmt.Sprintf("spec.topology.%s.replicas can not be 0 or less", string(nodeType)))) + } - err := druidValidateVolumes(&d.Spec.Topology.Overlords.PodTemplate, DruidNodeRoleOverlords) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("overlords").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } - err = druidValidateVolumesMountPaths(&d.Spec.Topology.Overlords.PodTemplate, DruidNodeRoleOverlords) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("overlords").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } + if node.StorageType == "" { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("storageType"), + dbName, + fmt.Sprintf("spec.topology.%s.storageType can not be empty", string(nodeType)))) + } else { + if node.StorageType != StorageTypeDurable && node.StorageType != StorageTypeEphemeral { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("storageType"), + dbName, + fmt.Sprintf("spec.topology.%s.storageType should either be durable or ephemeral", string(nodeType)))) } - if d.Spec.Topology.Routers != nil { - if *d.Spec.Topology.Routers.Replicas <= 0 { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("routers").Child("replicas"), - d.Name, - "number of replicas can not be 0 or less")) - } + } + if node.StorageType == StorageTypeEphemeral && node.Storage != nil { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("storage"), + dbName, + fmt.Sprintf("spec.topology.%s.storage can not be set when d.spec.topology.%s.storageType is Ephemeral", string(nodeType), string(nodeType)))) + } + if node.StorageType == StorageTypeDurable && node.EphemeralStorage != nil { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("ephemeralStorage"), + dbName, + fmt.Sprintf("spec.topology.%s.ephemeralStorage can not be set when d.spec.topology.%s.storageType is Durable", string(nodeType), string(nodeType)))) + } + if node.StorageType == StorageTypeDurable && node.Storage == nil { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("storage"), + dbName, + fmt.Sprintf("spec.topology.%s.storage needs to be set when spec.topology.%s.storageType is Durable", string(nodeType), string(nodeType)))) + } - err := druidValidateVolumes(&d.Spec.Topology.Routers.PodTemplate, DruidNodeRoleRouters) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("routers").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } - err = druidValidateVolumesMountPaths(&d.Spec.Topology.Routers.PodTemplate, DruidNodeRoleRouters) - if err != nil { - allErr = append(allErr, field.Invalid(field.NewPath("spec").Child("topology").Child("routers").Child("podTemplate").Child("spec").Child("volumes"), - d.Name, - err.Error())) - } - } + err := druidValidateVolumes(&node.PodTemplate, nodeType) + if err != nil { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("podTemplate").Child("spec").Child("volumes"), + dbName, + err.Error())) } - if len(allErr) == 0 { - return nil + err = druidValidateVolumesMountPaths(&node.PodTemplate, nodeType) + if err != nil { + *allErr = append(*allErr, field.Invalid(field.NewPath("spec").Child("topology").Child(string(nodeType)).Child("podTemplate").Child("spec").Child("volumes"), + dbName, + err.Error())) } - return allErr } func druidValidateVersion(d *Druid) error { diff --git a/apis/kubedb/v1alpha2/openapi_generated.go b/apis/kubedb/v1alpha2/openapi_generated.go index 6efeb8722e..847171db69 100644 --- a/apis/kubedb/v1alpha2/openapi_generated.go +++ b/apis/kubedb/v1alpha2/openapi_generated.go @@ -470,6 +470,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.Druid": schema_apimachinery_apis_kubedb_v1alpha2_Druid(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidApp": schema_apimachinery_apis_kubedb_v1alpha2_DruidApp(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidClusterTopology": schema_apimachinery_apis_kubedb_v1alpha2_DruidClusterTopology(ref), + "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidDataNode": schema_apimachinery_apis_kubedb_v1alpha2_DruidDataNode(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidList": schema_apimachinery_apis_kubedb_v1alpha2_DruidList(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidNode": schema_apimachinery_apis_kubedb_v1alpha2_DruidNode(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidSpec": schema_apimachinery_apis_kubedb_v1alpha2_DruidSpec(ref), @@ -23357,12 +23358,12 @@ func schema_apimachinery_apis_kubedb_v1alpha2_DruidClusterTopology(ref common.Re }, "middleManagers": { SchemaProps: spec.SchemaProps{ - Ref: ref("kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidNode"), + Ref: ref("kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidDataNode"), }, }, "historicals": { SchemaProps: spec.SchemaProps{ - Ref: ref("kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidNode"), + Ref: ref("kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidDataNode"), }, }, "brokers": { @@ -23379,7 +23380,102 @@ func schema_apimachinery_apis_kubedb_v1alpha2_DruidClusterTopology(ref common.Re }, }, Dependencies: []string{ - "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidNode"}, + "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidDataNode", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidNode"}, + } +} + +func schema_apimachinery_apis_kubedb_v1alpha2_DruidDataNode(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "replicas": { + SchemaProps: spec.SchemaProps{ + Description: "Replicas represents number of replicas for the specific type of node", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "suffix": { + SchemaProps: spec.SchemaProps{ + Description: "Suffix to append with node name", + Type: []string{"string"}, + Format: "", + }, + }, + "podTemplate": { + SchemaProps: spec.SchemaProps{ + Description: "PodTemplate is an optional configuration for pods used to expose database", + Default: map[string]interface{}{}, + Ref: ref("kmodules.xyz/offshoot-api/api/v2.PodTemplateSpec"), + }, + }, + "nodeSelector": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-map-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "tolerations": { + SchemaProps: spec.SchemaProps{ + Description: "If specified, the pod's tolerations.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/core/v1.Toleration"), + }, + }, + }, + }, + }, + "podPlacementPolicy": { + SchemaProps: spec.SchemaProps{ + Description: "PodPlacementPolicy is the reference of the podPlacementPolicy", + Ref: ref("k8s.io/api/core/v1.LocalObjectReference"), + }, + }, + "storageType": { + SchemaProps: spec.SchemaProps{ + Description: "StorageType specifies if the storage of this node is durable (default) or ephemeral.", + Type: []string{"string"}, + Format: "", + }, + }, + "storage": { + SchemaProps: spec.SchemaProps{ + Description: "Storage to specify how storage shall be used.", + Ref: ref("k8s.io/api/core/v1.PersistentVolumeClaimSpec"), + }, + }, + "ephemeralStorage": { + SchemaProps: spec.SchemaProps{ + Description: "EphemeralStorage spec to specify the configuration of ephemeral storage type.", + Ref: ref("k8s.io/api/core/v1.EmptyDirVolumeSource"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.EmptyDirVolumeSource", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PersistentVolumeClaimSpec", "k8s.io/api/core/v1.Toleration", "kmodules.xyz/offshoot-api/api/v2.PodTemplateSpec"}, } } @@ -23452,12 +23548,6 @@ func schema_apimachinery_apis_kubedb_v1alpha2_DruidNode(ref common.ReferenceCall Format: "", }, }, - "storage": { - SchemaProps: spec.SchemaProps{ - Description: "Storage to specify how storage shall be used.", - Ref: ref("k8s.io/api/core/v1.PersistentVolumeClaimSpec"), - }, - }, "podTemplate": { SchemaProps: spec.SchemaProps{ Description: "PodTemplate is an optional configuration for pods used to expose database", @@ -23506,17 +23596,11 @@ func schema_apimachinery_apis_kubedb_v1alpha2_DruidNode(ref common.ReferenceCall Ref: ref("k8s.io/api/core/v1.LocalObjectReference"), }, }, - "ephemeralStorage": { - SchemaProps: spec.SchemaProps{ - Description: "EphemeralStorage spec to specify the configuration of ephemeral storage type.", - Ref: ref("k8s.io/api/core/v1.EmptyDirVolumeSource"), - }, - }, }, }, }, Dependencies: []string{ - "k8s.io/api/core/v1.EmptyDirVolumeSource", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PersistentVolumeClaimSpec", "k8s.io/api/core/v1.Toleration", "kmodules.xyz/offshoot-api/api/v2.PodTemplateSpec"}, + "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.Toleration", "kmodules.xyz/offshoot-api/api/v2.PodTemplateSpec"}, } } @@ -23541,13 +23625,6 @@ func schema_apimachinery_apis_kubedb_v1alpha2_DruidSpec(ref common.ReferenceCall Ref: ref("kubedb.dev/apimachinery/apis/kubedb/v1alpha2.DruidClusterTopology"), }, }, - "storageType": { - SchemaProps: spec.SchemaProps{ - Description: "StorageType can be durable (default) or ephemeral.", - Type: []string{"string"}, - Format: "", - }, - }, "disableSecurity": { SchemaProps: spec.SchemaProps{ Description: "disable security. It disables authentication security of user. If unset, default is false", @@ -28575,13 +28652,6 @@ func schema_apimachinery_apis_kubedb_v1alpha2_PgBouncerStatus(ref common.Referen Ref: ref("kubedb.dev/apimachinery/apis/kubedb/v1alpha2.Gateway"), }, }, - "resourceVersionOfBackendSecret": { - SchemaProps: spec.SchemaProps{ - Description: "It is to decide if the Auth_file needs to get updated by comparing with the Resource Version of the Backend Secret", - Type: []string{"string"}, - Format: "", - }, - }, }, }, }, diff --git a/apis/kubedb/v1alpha2/pgbouncer_types.go b/apis/kubedb/v1alpha2/pgbouncer_types.go index a9e4830fa7..4723986f0f 100644 --- a/apis/kubedb/v1alpha2/pgbouncer_types.go +++ b/apis/kubedb/v1alpha2/pgbouncer_types.go @@ -210,9 +210,6 @@ type PgBouncerStatus struct { Conditions []kmapi.Condition `json:"conditions,omitempty"` // +optional Gateway *Gateway `json:"gateway,omitempty"` - // It is to decide if the Auth_file needs to get updated by comparing with the Resource Version of the Backend Secret - // +optional - ResourceVersionOfBackendSecret string `json:"resourceVersionOfBackendSecret,omitempty" protobuf:"bytes,6,opt,name=resourceVersionOfBackendSecret"` } // +kubebuilder:validation:Enum=disable;allow;prefer;require;verify-ca;verify-full diff --git a/apis/kubedb/v1alpha2/zz_generated.deepcopy.go b/apis/kubedb/v1alpha2/zz_generated.deepcopy.go index 9ea86c5b64..2fa5faaec4 100644 --- a/apis/kubedb/v1alpha2/zz_generated.deepcopy.go +++ b/apis/kubedb/v1alpha2/zz_generated.deepcopy.go @@ -382,12 +382,12 @@ func (in *DruidClusterTopology) DeepCopyInto(out *DruidClusterTopology) { } if in.MiddleManagers != nil { in, out := &in.MiddleManagers, &out.MiddleManagers - *out = new(DruidNode) + *out = new(DruidDataNode) (*in).DeepCopyInto(*out) } if in.Historicals != nil { in, out := &in.Historicals, &out.Historicals - *out = new(DruidNode) + *out = new(DruidDataNode) (*in).DeepCopyInto(*out) } if in.Brokers != nil { @@ -413,6 +413,33 @@ func (in *DruidClusterTopology) DeepCopy() *DruidClusterTopology { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DruidDataNode) DeepCopyInto(out *DruidDataNode) { + *out = *in + in.DruidNode.DeepCopyInto(&out.DruidNode) + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = new(corev1.PersistentVolumeClaimSpec) + (*in).DeepCopyInto(*out) + } + if in.EphemeralStorage != nil { + in, out := &in.EphemeralStorage, &out.EphemeralStorage + *out = new(corev1.EmptyDirVolumeSource) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DruidDataNode. +func (in *DruidDataNode) DeepCopy() *DruidDataNode { + if in == nil { + return nil + } + out := new(DruidDataNode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DruidList) DeepCopyInto(out *DruidList) { *out = *in @@ -454,11 +481,6 @@ func (in *DruidNode) DeepCopyInto(out *DruidNode) { *out = new(int32) **out = **in } - if in.Storage != nil { - in, out := &in.Storage, &out.Storage - *out = new(corev1.PersistentVolumeClaimSpec) - (*in).DeepCopyInto(*out) - } in.PodTemplate.DeepCopyInto(&out.PodTemplate) if in.NodeSelector != nil { in, out := &in.NodeSelector, &out.NodeSelector @@ -479,11 +501,6 @@ func (in *DruidNode) DeepCopyInto(out *DruidNode) { *out = new(corev1.LocalObjectReference) **out = **in } - if in.EphemeralStorage != nil { - in, out := &in.EphemeralStorage, &out.EphemeralStorage - *out = new(corev1.EmptyDirVolumeSource) - (*in).DeepCopyInto(*out) - } return } diff --git a/crds/kubedb.com_druids.yaml b/crds/kubedb.com_druids.yaml index f619f3d13c..f01de905f4 100644 --- a/crds/kubedb.com_druids.yaml +++ b/crds/kubedb.com_druids.yaml @@ -370,11 +370,6 @@ spec: - alias type: object type: array - storageType: - enum: - - Durable - - Ephemeral - type: string terminationPolicy: enum: - Halt @@ -386,17 +381,6 @@ spec: properties: brokers: properties: - ephemeralStorage: - properties: - medium: - type: string - sizeLimit: - 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 - type: object nodeSelector: additionalProperties: type: string @@ -3306,91 +3290,6 @@ spec: default: 1 format: int32 type: integer - storage: - properties: - accessModes: - items: - type: string - type: array - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object suffix: type: string tolerations: @@ -3412,17 +3311,6 @@ spec: type: object coordinators: properties: - ephemeralStorage: - properties: - medium: - type: string - sizeLimit: - 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 - type: object nodeSelector: additionalProperties: type: string @@ -6332,91 +6220,6 @@ spec: default: 1 format: int32 type: integer - storage: - properties: - accessModes: - items: - type: string - type: array - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object suffix: type: string tolerations: @@ -9443,6 +9246,11 @@ spec: volumeName: type: string type: object + storageType: + enum: + - Durable + - Ephemeral + type: string suffix: type: string tolerations: @@ -12469,6 +12277,11 @@ spec: volumeName: type: string type: object + storageType: + enum: + - Durable + - Ephemeral + type: string suffix: type: string tolerations: @@ -12490,17 +12303,6 @@ spec: type: object overlords: properties: - ephemeralStorage: - properties: - medium: - type: string - sizeLimit: - 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 - type: object nodeSelector: additionalProperties: type: string @@ -15410,91 +15212,6 @@ spec: default: 1 format: int32 type: integer - storage: - properties: - accessModes: - items: - type: string - type: array - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object suffix: type: string tolerations: @@ -15516,17 +15233,6 @@ spec: type: object routers: properties: - ephemeralStorage: - properties: - medium: - type: string - sizeLimit: - 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 - type: object nodeSelector: additionalProperties: type: string @@ -18436,91 +18142,6 @@ spec: default: 1 format: int32 type: integer - storage: - properties: - accessModes: - items: - type: string - type: array - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object suffix: type: string tolerations: diff --git a/crds/kubedb.com_pgbouncers.yaml b/crds/kubedb.com_pgbouncers.yaml index ff58db10dc..7d6fd7c887 100644 --- a/crds/kubedb.com_pgbouncers.yaml +++ b/crds/kubedb.com_pgbouncers.yaml @@ -3150,8 +3150,6 @@ spec: - Halted - Unknown type: string - resourceVersionOfBackendSecret: - type: string type: object type: object served: true diff --git a/crds/ui.kubedb.com_pgbouncerinsights.yaml b/crds/ui.kubedb.com_pgbouncerinsights.yaml index 98ed27fe41..1ebf7ec1a1 100644 --- a/crds/ui.kubedb.com_pgbouncerinsights.yaml +++ b/crds/ui.kubedb.com_pgbouncerinsights.yaml @@ -209,8 +209,6 @@ spec: - Halted - Unknown type: string - resourceVersionOfBackendSecret: - type: string type: object type: object served: true diff --git a/openapi/swagger.json b/openapi/swagger.json index dfce4e4e1c..1f115da724 100644 --- a/openapi/swagger.json +++ b/openapi/swagger.json @@ -25248,10 +25248,6 @@ "phase": { "description": "Specifies the current phase of the database", "type": "string" - }, - "resourceVersionOfBackendSecret": { - "description": "It is to decide if the Auth_file needs to get updated by comparing with the Resource Version of the Backend Secret", - "type": "string" } } },