diff --git a/apis/kubedb/v1alpha2/constants.go b/apis/kubedb/v1alpha2/constants.go index 766d2d01e6..b0c2d5bbbc 100644 --- a/apis/kubedb/v1alpha2/constants.go +++ b/apis/kubedb/v1alpha2/constants.go @@ -130,6 +130,9 @@ const ( NodeTypeMongos = "mongos" NodeTypeShard = "shard" NodeTypeConfig = "configsvr" + NodeTypeArbiter = "arbiter" + NodeTypeReplica = "replica" + NodeTypeStandalone = "standalone" MongoDBWorkDirectoryName = "workdir" MongoDBWorkDirectoryPath = "/work-dir" @@ -151,6 +154,9 @@ const ( MongoDBInitScriptDirectoryName = "init-scripts" MongoDBInitScriptDirectoryPath = "/init-scripts" + MongoDBInitialDirectoryName = "initial-script" + MongoDBInitialDirectoryPath = "/docker-entrypoint-initdb.d" + MongoDBClientCertDirectoryName = "client-cert" MongoDBClientCertDirectoryPath = "/client-cert" diff --git a/apis/kubedb/v1alpha2/mongodb_helpers.go b/apis/kubedb/v1alpha2/mongodb_helpers.go index dd6d9c3ff2..0f1ebf09c9 100644 --- a/apis/kubedb/v1alpha2/mongodb_helpers.go +++ b/apis/kubedb/v1alpha2/mongodb_helpers.go @@ -18,6 +18,7 @@ package v1alpha2 import ( "fmt" + "strconv" "strings" "kubedb.dev/apimachinery/apis" @@ -56,10 +57,23 @@ const ( MongoDBShardLabelKey = "mongodb.kubedb.com/node.shard" MongoDBConfigLabelKey = "mongodb.kubedb.com/node.config" MongoDBMongosLabelKey = "mongodb.kubedb.com/node.mongos" + MongoDBTypeLabelKey = "mongodb.kubedb.com/node.type" MongoDBShardAffinityTemplateVar = "SHARD_INDEX" ) +type MongoShellScriptName string + +const ( + ScriptNameCommon MongoShellScriptName = "common.sh" + ScriptNameInstall MongoShellScriptName = "install.sh" + ScriptNameMongos MongoShellScriptName = "mongos.sh" + ScriptNameShard MongoShellScriptName = "sharding.sh" + ScriptNameConfig MongoShellScriptName = "configdb.sh" + ScriptNameReplicaset MongoShellScriptName = "replicaset.sh" + ScriptNameArbiter MongoShellScriptName = "arbiter.sh" +) + func (m MongoDB) OffshootName() string { return m.Name } @@ -126,6 +140,20 @@ func (m MongoDB) ConfigSvrRepSetName() string { return repSetName } +func (m MongoDB) ArbiterNodeName() string { + if m.Spec.ReplicaSet == nil || m.Spec.Arbiter == nil { + return "" + } + return fmt.Sprintf("%v-%v", m.OffshootName(), NodeTypeArbiter) +} + +func (m MongoDB) ArbiterShardNodeName(nodeNum int32) string { + if m.Spec.ShardTopology == nil || m.Spec.Arbiter == nil { + return "" + } + return fmt.Sprintf("%v-%v", m.ShardNodeName(nodeNum), NodeTypeArbiter) +} + func (m MongoDB) OffshootSelectors() map[string]string { return map[string]string{ meta_util.NameLabelKey: m.ResourceFQN(), @@ -134,12 +162,24 @@ func (m MongoDB) OffshootSelectors() map[string]string { } } +func (m MongoDB) OffshootSelectorsWhenArbiter() map[string]string { + return meta_util.OverwriteKeys(m.OffshootSelectors(), map[string]string{ + MongoDBTypeLabelKey: NodeTypeReplica, + }) +} + func (m MongoDB) ShardSelectors(nodeNum int32) map[string]string { return meta_util.OverwriteKeys(m.OffshootSelectors(), map[string]string{ MongoDBShardLabelKey: m.ShardNodeName(nodeNum), }) } +func (m MongoDB) ShardSelectorsWhenArbiter(nodeNum int32) map[string]string { + return meta_util.OverwriteKeys(m.ShardSelectors(nodeNum), map[string]string{ + MongoDBTypeLabelKey: NodeTypeShard, + }) +} + func (m MongoDB) ConfigSvrSelectors() map[string]string { return meta_util.OverwriteKeys(m.OffshootSelectors(), map[string]string{ MongoDBConfigLabelKey: m.ConfigSvrNodeName(), @@ -152,10 +192,26 @@ func (m MongoDB) MongosSelectors() map[string]string { }) } +func (m MongoDB) ArbiterSelectors() map[string]string { + return meta_util.OverwriteKeys(m.OffshootSelectors(), map[string]string{ + MongoDBTypeLabelKey: NodeTypeArbiter, + }) +} + +func (m MongoDB) ArbiterShardSelectors(nodeNum int32) map[string]string { + return meta_util.OverwriteKeys(m.ShardSelectors(nodeNum), map[string]string{ + MongoDBTypeLabelKey: NodeTypeArbiter, + }) +} + func (m MongoDB) OffshootLabels() map[string]string { return m.offshootLabels(m.OffshootSelectors(), nil) } +func (m MongoDB) OffshootLabelsWhenArbiter() map[string]string { + return meta_util.OverwriteKeys(m.OffshootLabels(), m.OffshootSelectorsWhenArbiter()) +} + func (m MongoDB) PodLabels(podTemplateLabels map[string]string, extraLabels ...map[string]string) map[string]string { return m.offshootLabels(meta_util.OverwriteKeys(m.OffshootSelectors(), extraLabels...), podTemplateLabels) } @@ -178,6 +234,10 @@ func (m MongoDB) ShardLabels(nodeNum int32) map[string]string { return meta_util.OverwriteKeys(m.OffshootLabels(), m.ShardSelectors(nodeNum)) } +func (m MongoDB) ShardLabelsWhenArbiter(nodeNum int32) map[string]string { + return meta_util.OverwriteKeys(m.OffshootLabels(), m.ShardSelectorsWhenArbiter(nodeNum)) +} + func (m MongoDB) ConfigSvrLabels() map[string]string { return meta_util.OverwriteKeys(m.OffshootLabels(), m.ConfigSvrSelectors()) } @@ -186,6 +246,45 @@ func (m MongoDB) MongosLabels() map[string]string { return meta_util.OverwriteKeys(m.OffshootLabels(), m.MongosSelectors()) } +func (m MongoDB) ArbiterLabels() map[string]string { + return meta_util.OverwriteKeys(m.OffshootLabels(), m.ArbiterSelectors()) +} + +func (m MongoDB) ArbiterShardLabels(nodeNum int32) map[string]string { + return meta_util.OverwriteKeys(m.OffshootLabels(), m.ArbiterShardSelectors(nodeNum)) +} + +func (m MongoDB) GetCorrespondingReplicaStsName(arbStsName string) string { + if !strings.HasSuffix(arbStsName, "-"+NodeTypeArbiter) { + panic(fmt.Sprintf("%s does not have -%s as suffix", arbStsName, NodeTypeArbiter)) + } + return arbStsName[:strings.LastIndex(arbStsName, "-")] +} + +func (m MongoDB) GetCorrespondingArbiterStsName(replStsName string) string { + return replStsName + "-" + NodeTypeArbiter +} + +func (m MongoDB) GetShardNumber(shardName string) int { + // this will return 123 from shardName dbname-shard123 + last := -1 + for i := len(shardName) - 1; i >= 0; i-- { + if shardName[i] >= '0' && shardName[i] <= '9' { + continue + } + last = i + break + } + if last == len(shardName)-1 { + panic(fmt.Sprintf("invalid shard name %s ", shardName)) + } + shardNumber, err := strconv.Atoi(shardName[last+1:]) + if err != nil { + return 0 + } + return shardNumber +} + func (m MongoDB) ResourceFQN() string { return fmt.Sprintf("%s.%s", ResourcePluralMongoDB, kubedb.GroupName) } @@ -211,11 +310,14 @@ func (m MongoDB) ServiceName() string { } // Governing Service Name. Here, name parameter is either -// OffshootName, ShardNodeName or ConfigSvrNodeName +// OffshootName, ShardNodeName, ConfigSvrNodeName or ArbiterNodeName func (m MongoDB) GoverningServiceName(name string) string { if name == "" { panic(fmt.Sprintf("StatefulSet name is missing for MongoDB %s/%s", m.Namespace, m.Name)) } + if strings.HasSuffix(name, "-"+NodeTypeArbiter) { + name = m.GetCorrespondingReplicaStsName(name) + } return name + "-pods" } @@ -234,11 +336,15 @@ func (m MongoDB) HostAddress() string { } func (m MongoDB) Hosts() []string { - hosts := []string{fmt.Sprintf("%v-0.%v.%v.svc", m.Name, m.GoverningServiceName(m.OffshootName()), m.Namespace)} + hosts := []string{fmt.Sprintf("%v-0.%v.%v.svc:%v", m.Name, m.GoverningServiceName(m.OffshootName()), m.Namespace, MongoDBDatabasePort)} if m.Spec.ReplicaSet != nil { hosts = make([]string, *m.Spec.Replicas) for i := 0; i < int(pointer.Int32(m.Spec.Replicas)); i++ { - hosts[i] = fmt.Sprintf("%v-%d.%v.%v.svc", m.Name, i, m.GoverningServiceName(m.OffshootName()), m.Namespace) + hosts[i] = fmt.Sprintf("%v-%d.%v.%v.svc:%v", m.Name, i, m.GoverningServiceName(m.OffshootName()), m.Namespace, MongoDBDatabasePort) + } + if m.Spec.Arbiter != nil { + s := fmt.Sprintf("%v-0.%v.%v.svc:%v", m.ArbiterNodeName(), m.GoverningServiceName(m.OffshootName()), m.Namespace, MongoDBDatabasePort) + hosts = append(hosts, s) } } return hosts @@ -261,6 +367,10 @@ func (m MongoDB) ShardHosts(nodeNum int32) []string { for i := 0; i < int(m.Spec.ShardTopology.Shard.Replicas); i++ { hosts[i] = fmt.Sprintf("%v-%d.%v.%v.svc:%v", m.ShardNodeName(nodeNum), i, m.GoverningServiceName(m.ShardNodeName(nodeNum)), m.Namespace, MongoDBDatabasePort) } + if m.Spec.Arbiter != nil { + s := fmt.Sprintf("%v-0.%v.%v.svc:%v", m.ArbiterShardNodeName(nodeNum), m.GoverningServiceName(m.ShardNodeName(nodeNum)), m.Namespace, MongoDBDatabasePort) + hosts = append(hosts, s) + } return hosts } @@ -350,6 +460,17 @@ func (m MongoDB) StatsServiceLabels() map[string]string { return m.ServiceLabels(StatsServiceAlias, map[string]string{LabelRole: RoleStats}) } +// StorageType = Durable +// storageEngine = wiredTiger +// TerminationPolicy = Delete +// SSLMode = disabled +// clusterAuthMode = keyFile if sslMode is disabled or allowSSL. & x509 otherwise +// +// podTemplate.Spec.ServiceAccountName = DB_NAME +// set mongos lifecycle command, to shut down the db before stopping +// it sets default ReadinessProbe, livelinessProbe, affinity & ResourceLimits +// then set TLSDefaults & monitor Defaults + func (m *MongoDB) SetDefaults(mgVersion *v1alpha1.MongoDBVersion, topology *core_util.Topology) { if m == nil { return @@ -381,6 +502,9 @@ func (m *MongoDB) SetDefaults(mgVersion *v1alpha1.MongoDBVersion, topology *core apis.SetDefaultResourceLimits(&m.Spec.ShardTopology.Mongos.PodTemplate.Spec.Resources, DefaultResources) apis.SetDefaultResourceLimits(&m.Spec.ShardTopology.Shard.PodTemplate.Spec.Resources, DefaultResources) apis.SetDefaultResourceLimits(&m.Spec.ShardTopology.ConfigServer.PodTemplate.Spec.Resources, DefaultResources) + if m.Spec.Arbiter != nil { + apis.SetDefaultResourceLimits(&m.Spec.Arbiter.PodTemplate.Spec.Resources, DefaultResources) + } if m.Spec.ShardTopology.Mongos.PodTemplate.Spec.Lifecycle == nil { m.Spec.ShardTopology.Mongos.PodTemplate.Spec.Lifecycle = new(core.Lifecycle) @@ -410,11 +534,18 @@ func (m *MongoDB) SetDefaults(mgVersion *v1alpha1.MongoDBVersion, topology *core m.setDefaultProbes(&m.Spec.ShardTopology.Shard.PodTemplate, mgVersion) m.setDefaultProbes(&m.Spec.ShardTopology.ConfigServer.PodTemplate, mgVersion) m.setDefaultProbes(&m.Spec.ShardTopology.Mongos.PodTemplate, mgVersion) + if m.Spec.Arbiter != nil { + m.setDefaultProbes(&m.Spec.Arbiter.PodTemplate, mgVersion, true) + } // set default affinity (PodAntiAffinity) shardLabels := m.OffshootSelectors() shardLabels[MongoDBShardLabelKey] = m.ShardNodeTemplate() m.setDefaultAffinity(&m.Spec.ShardTopology.Shard.PodTemplate, shardLabels, topology) + if m.Spec.Arbiter != nil { + // the labels are same as the shard + m.setDefaultAffinity(&m.Spec.Arbiter.PodTemplate, shardLabels, topology) + } configServerLabels := m.OffshootSelectors() configServerLabels[MongoDBConfigLabelKey] = m.ConfigSvrNodeName() @@ -441,6 +572,12 @@ func (m *MongoDB) SetDefaults(mgVersion *v1alpha1.MongoDBVersion, topology *core m.setDefaultAffinity(m.Spec.PodTemplate, m.OffshootSelectors(), topology) apis.SetDefaultResourceLimits(&m.Spec.PodTemplate.Spec.Resources, DefaultResources) + + if m.Spec.Arbiter != nil { + m.setDefaultProbes(&m.Spec.Arbiter.PodTemplate, mgVersion, true) + m.setDefaultAffinity(&m.Spec.Arbiter.PodTemplate, m.OffshootSelectors(), topology) + apis.SetDefaultResourceLimits(&m.Spec.Arbiter.PodTemplate.Spec.Resources, DefaultResources) + } } m.SetTLSDefaults() @@ -458,17 +595,18 @@ func (m *MongoDB) SetTLSDefaults() { defaultServerOrg := []string{KubeDBOrganization} defaultServerOrgUnit := []string{string(MongoDBServerCert)} - if m.Spec.ShardTopology != nil { - _, cert := kmapi.GetCertificate(m.Spec.TLS.Certificates, string(MongoDBServerCert)) - if cert != nil && cert.Subject != nil { - if cert.Subject.Organizations != nil { - defaultServerOrg = cert.Subject.Organizations - } - if cert.Subject.OrganizationalUnits != nil { - defaultServerOrgUnit = cert.Subject.OrganizationalUnits - } + + _, cert := kmapi.GetCertificate(m.Spec.TLS.Certificates, string(MongoDBServerCert)) + if cert != nil && cert.Subject != nil { + if cert.Subject.Organizations != nil { + defaultServerOrg = cert.Subject.Organizations + } + if cert.Subject.OrganizationalUnits != nil { + defaultServerOrgUnit = cert.Subject.OrganizationalUnits } + } + if m.Spec.ShardTopology != nil || (m.Spec.ReplicaSet != nil && m.Spec.Arbiter != nil) { m.Spec.TLS.Certificates = kmapi.SetMissingSpecForCertificate(m.Spec.TLS.Certificates, kmapi.CertificateSpec{ Alias: string(MongoDBServerCert), SecretName: "", @@ -477,20 +615,9 @@ func (m *MongoDB) SetTLSDefaults() { OrganizationalUnits: defaultServerOrgUnit, }, }) - // reset secret name to empty string, since multiple secrets will be created for each StatefulSet. m.Spec.TLS.Certificates = kmapi.SetSecretNameForCertificate(m.Spec.TLS.Certificates, string(MongoDBServerCert), "") } else { - _, cert := kmapi.GetCertificate(m.Spec.TLS.Certificates, string(MongoDBServerCert)) - if cert != nil && cert.Subject != nil { - if cert.Subject.Organizations != nil { - defaultServerOrg = cert.Subject.Organizations - } - if cert.Subject.OrganizationalUnits != nil { - defaultServerOrgUnit = cert.Subject.OrganizationalUnits - } - } - m.Spec.TLS.Certificates = kmapi.SetMissingSpecForCertificate(m.Spec.TLS.Certificates, kmapi.CertificateSpec{ Alias: string(MongoDBServerCert), SecretName: m.CertificateName(MongoDBServerCert, ""), @@ -501,9 +628,10 @@ func (m *MongoDB) SetTLSDefaults() { }) } + // Client-cert defaultClientOrg := []string{KubeDBOrganization} defaultClientOrgUnit := []string{string(MongoDBClientCert)} - _, cert := kmapi.GetCertificate(m.Spec.TLS.Certificates, string(MongoDBClientCert)) + _, cert = kmapi.GetCertificate(m.Spec.TLS.Certificates, string(MongoDBClientCert)) if cert != nil && cert.Subject != nil { if cert.Subject.Organizations != nil { defaultClientOrg = cert.Subject.Organizations @@ -521,6 +649,7 @@ func (m *MongoDB) SetTLSDefaults() { }, }) + // Metrics-exporter-cert defaultExporterOrg := []string{KubeDBOrganization} defaultExporterOrgUnit := []string{string(MongoDBMetricsExporterCert)} _, cert = kmapi.GetCertificate(m.Spec.TLS.Certificates, string(MongoDBMetricsExporterCert)) @@ -542,7 +671,7 @@ func (m *MongoDB) SetTLSDefaults() { }) } -func (m *MongoDB) getCmdForProbes(mgVersion *v1alpha1.MongoDBVersion) []string { +func (m *MongoDB) getCmdForProbes(mgVersion *v1alpha1.MongoDBVersion, isArbiter ...bool) []string { var sslArgs string if m.Spec.SSLMode == SSLModeRequireSSL { sslArgs = fmt.Sprintf("--tls --tlsCAFile=%v/%v --tlsCertificateKeyFile=%v/%v", @@ -561,21 +690,25 @@ func (m *MongoDB) getCmdForProbes(mgVersion *v1alpha1.MongoDBVersion) []string { } } + var authArgs string + if len(isArbiter) == 0 { // not arbiter + authArgs = "--username=$MONGO_INITDB_ROOT_USERNAME --password=$MONGO_INITDB_ROOT_PASSWORD --authenticationDatabase=admin" + } return []string{ "bash", "-c", - fmt.Sprintf(`set -x; if [[ $(mongo admin --host=localhost %v --username=$MONGO_INITDB_ROOT_USERNAME --password=$MONGO_INITDB_ROOT_PASSWORD --authenticationDatabase=admin --quiet --eval "db.adminCommand('ping').ok" ) -eq "1" ]]; then + fmt.Sprintf(`set -x; if [[ $(mongo admin --host=localhost %v %v --quiet --eval "db.adminCommand('ping').ok" ) -eq "1" ]]; then exit 0 fi - exit 1`, sslArgs), + exit 1`, sslArgs, authArgs), } } -func (m *MongoDB) GetDefaultLivenessProbeSpec(mgVersion *v1alpha1.MongoDBVersion) *core.Probe { +func (m *MongoDB) GetDefaultLivenessProbeSpec(mgVersion *v1alpha1.MongoDBVersion, isArbiter ...bool) *core.Probe { return &core.Probe{ Handler: core.Handler{ Exec: &core.ExecAction{ - Command: m.getCmdForProbes(mgVersion), + Command: m.getCmdForProbes(mgVersion, isArbiter...), }, }, FailureThreshold: 3, @@ -585,11 +718,11 @@ func (m *MongoDB) GetDefaultLivenessProbeSpec(mgVersion *v1alpha1.MongoDBVersion } } -func (m *MongoDB) GetDefaultReadinessProbeSpec(mgVersion *v1alpha1.MongoDBVersion) *core.Probe { +func (m *MongoDB) GetDefaultReadinessProbeSpec(mgVersion *v1alpha1.MongoDBVersion, isArbiter ...bool) *core.Probe { return &core.Probe{ Handler: core.Handler{ Exec: &core.ExecAction{ - Command: m.getCmdForProbes(mgVersion), + Command: m.getCmdForProbes(mgVersion, isArbiter...), }, }, FailureThreshold: 3, @@ -603,16 +736,16 @@ func (m *MongoDB) GetDefaultReadinessProbeSpec(mgVersion *v1alpha1.MongoDBVersio // In operator, check if the value of probe fields is "{}". // For "{}", ignore readinessprobe or livenessprobe in statefulset. // ref: https://github.com/helm/charts/blob/345ba987722350ffde56ec34d2928c0b383940aa/stable/mongodb/templates/deployment-standalone.yaml#L93 -func (m *MongoDB) setDefaultProbes(podTemplate *ofst.PodTemplateSpec, mgVersion *v1alpha1.MongoDBVersion) { +func (m *MongoDB) setDefaultProbes(podTemplate *ofst.PodTemplateSpec, mgVersion *v1alpha1.MongoDBVersion, isArbiter ...bool) { if podTemplate == nil { return } if podTemplate.Spec.LivenessProbe == nil { - podTemplate.Spec.LivenessProbe = m.GetDefaultLivenessProbeSpec(mgVersion) + podTemplate.Spec.LivenessProbe = m.GetDefaultLivenessProbeSpec(mgVersion, isArbiter...) } if podTemplate.Spec.ReadinessProbe == nil { - podTemplate.Spec.ReadinessProbe = m.GetDefaultReadinessProbeSpec(mgVersion) + podTemplate.Spec.ReadinessProbe = m.GetDefaultReadinessProbeSpec(mgVersion, isArbiter...) } } @@ -709,7 +842,13 @@ func (m *MongoDB) CertificateName(alias MongoDBCertificateAlias, stsName string) panic(fmt.Sprintf("StatefulSet name required to compute %s certificate name for MongoDB %s/%s", alias, m.Namespace, m.Name)) } return meta_util.NameWithSuffix(stsName, fmt.Sprintf("%s-cert", string(alias))) + } else if m.Spec.ReplicaSet != nil && alias == MongoDBServerCert { + if stsName == "" { + return meta_util.NameWithSuffix(m.Name, fmt.Sprintf("%s-cert", string(alias))) // for general replica + } + return meta_util.NameWithSuffix(stsName, fmt.Sprintf("%s-cert", string(alias))) // for arbiter } + // for standAlone server-cert. And for client-cert & metrics-exporter-cert of all type of replica & shard, stsName is not needed. return meta_util.NameWithSuffix(m.Name, fmt.Sprintf("%s-cert", string(alias))) } diff --git a/apis/kubedb/v1alpha2/mongodb_types.go b/apis/kubedb/v1alpha2/mongodb_types.go index 021d56d16d..58d9cb9053 100644 --- a/apis/kubedb/v1alpha2/mongodb_types.go +++ b/apis/kubedb/v1alpha2/mongodb_types.go @@ -133,6 +133,12 @@ type MongoDBSpec struct { // +kubebuilder:default={namespaces:{from: Same}} // +optional AllowedSchemas *AllowedConsumers `json:"allowedSchemas,omitempty"` + + // Mongo Arbiter component of mongodb. + // More info: https://docs.mongodb.com/manual/core/replica-set-arbiter/ + // +optional + // +nullable + Arbiter *MongoArbiterNode `json:"arbiter"` } // +kubebuilder:validation:Enum=server;client;metrics-exporter @@ -250,6 +256,16 @@ type MongoDBMongosNode struct { MongoDBNode `json:",inline"` } +type MongoArbiterNode struct { + // ConfigSecret is an optional field to provide custom configuration file for database (i.e mongod.cnf). + // If specified, this file will be used as configuration file otherwise default configuration file will be used. + ConfigSecret *core.LocalObjectReference `json:"configSecret,omitempty"` + + // PodTemplate is an optional configuration for pods used to expose database + // +optional + PodTemplate ofst.PodTemplateSpec `json:"podTemplate,omitempty"` +} + type MongoDBNode struct { // Replicas represents number of replicas of this specific node. // If current node has replicaset enabled, then replicas is the amount of replicaset nodes. diff --git a/apis/kubedb/v1alpha2/openapi_generated.go b/apis/kubedb/v1alpha2/openapi_generated.go index 94f4dabddd..cdb1db5b8c 100644 --- a/apis/kubedb/v1alpha2/openapi_generated.go +++ b/apis/kubedb/v1alpha2/openapi_generated.go @@ -444,6 +444,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MemcachedList": schema_apimachinery_apis_kubedb_v1alpha2_MemcachedList(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MemcachedSpec": schema_apimachinery_apis_kubedb_v1alpha2_MemcachedSpec(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MemcachedStatus": schema_apimachinery_apis_kubedb_v1alpha2_MemcachedStatus(ref), + "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoArbiterNode": schema_apimachinery_apis_kubedb_v1alpha2_MongoArbiterNode(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoDB": schema_apimachinery_apis_kubedb_v1alpha2_MongoDB(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoDBConfigNode": schema_apimachinery_apis_kubedb_v1alpha2_MongoDBConfigNode(ref), "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoDBList": schema_apimachinery_apis_kubedb_v1alpha2_MongoDBList(ref), @@ -22068,6 +22069,33 @@ func schema_apimachinery_apis_kubedb_v1alpha2_MemcachedStatus(ref common.Referen } } +func schema_apimachinery_apis_kubedb_v1alpha2_MongoArbiterNode(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "configSecret": { + SchemaProps: spec.SchemaProps{ + Description: "ConfigSecret is an optional field to provide custom configuration file for database (i.e mongod.cnf). If specified, this file will be used as configuration file otherwise default configuration file will be used.", + Ref: ref("k8s.io/api/core/v1.LocalObjectReference"), + }, + }, + "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/v1.PodTemplateSpec"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.LocalObjectReference", "kmodules.xyz/offshoot-api/api/v1.PodTemplateSpec"}, + } +} + func schema_apimachinery_apis_kubedb_v1alpha2_MongoDB(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -22579,12 +22607,18 @@ func schema_apimachinery_apis_kubedb_v1alpha2_MongoDBSpec(ref common.ReferenceCa Ref: ref("kubedb.dev/apimachinery/apis/kubedb/v1alpha2.AllowedConsumers"), }, }, + "arbiter": { + SchemaProps: spec.SchemaProps{ + Description: "Mongo Arbiter component of mongodb. More info: https://docs.mongodb.com/manual/core/replica-set-arbiter/", + Ref: ref("kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoArbiterNode"), + }, + }, }, Required: []string{"version"}, }, }, Dependencies: []string{ - "k8s.io/api/core/v1.EmptyDirVolumeSource", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PersistentVolumeClaimSpec", "kmodules.xyz/client-go/api/v1.TLSConfig", "kmodules.xyz/monitoring-agent-api/api/v1.AgentSpec", "kmodules.xyz/offshoot-api/api/v1.PodTemplateSpec", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.AllowedConsumers", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.CoordinatorSpec", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.InitSpec", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoDBReplicaSet", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoDBShardingTopology", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.NamedServiceTemplateSpec"}, + "k8s.io/api/core/v1.EmptyDirVolumeSource", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PersistentVolumeClaimSpec", "kmodules.xyz/client-go/api/v1.TLSConfig", "kmodules.xyz/monitoring-agent-api/api/v1.AgentSpec", "kmodules.xyz/offshoot-api/api/v1.PodTemplateSpec", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.AllowedConsumers", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.CoordinatorSpec", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.InitSpec", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoArbiterNode", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoDBReplicaSet", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.MongoDBShardingTopology", "kubedb.dev/apimachinery/apis/kubedb/v1alpha2.NamedServiceTemplateSpec"}, } } diff --git a/apis/kubedb/v1alpha2/zz_generated.deepcopy.go b/apis/kubedb/v1alpha2/zz_generated.deepcopy.go index 1c6169aa82..84a7ba037a 100644 --- a/apis/kubedb/v1alpha2/zz_generated.deepcopy.go +++ b/apis/kubedb/v1alpha2/zz_generated.deepcopy.go @@ -1027,6 +1027,28 @@ func (in *MemcachedStatus) DeepCopy() *MemcachedStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongoArbiterNode) DeepCopyInto(out *MongoArbiterNode) { + *out = *in + if in.ConfigSecret != nil { + in, out := &in.ConfigSecret, &out.ConfigSecret + *out = new(corev1.LocalObjectReference) + **out = **in + } + in.PodTemplate.DeepCopyInto(&out.PodTemplate) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoArbiterNode. +func (in *MongoArbiterNode) DeepCopy() *MongoArbiterNode { + if in == nil { + return nil + } + out := new(MongoArbiterNode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongoDB) DeepCopyInto(out *MongoDB) { *out = *in @@ -1292,6 +1314,11 @@ func (in *MongoDBSpec) DeepCopyInto(out *MongoDBSpec) { *out = new(AllowedConsumers) (*in).DeepCopyInto(*out) } + if in.Arbiter != nil { + in, out := &in.Arbiter, &out.Arbiter + *out = new(MongoArbiterNode) + (*in).DeepCopyInto(*out) + } return } diff --git a/apis/ops/v1alpha1/mongodb_ops_types.go b/apis/ops/v1alpha1/mongodb_ops_types.go index a19d1e5736..1562f34d56 100644 --- a/apis/ops/v1alpha1/mongodb_ops_types.go +++ b/apis/ops/v1alpha1/mongodb_ops_types.go @@ -123,6 +123,7 @@ type MongoDBVerticalScalingSpec struct { Mongos *core.ResourceRequirements `json:"mongos,omitempty"` ConfigServer *core.ResourceRequirements `json:"configServer,omitempty"` Shard *core.ResourceRequirements `json:"shard,omitempty"` + Arbiter *core.ResourceRequirements `json:"arbiter,omitempty"` Exporter *core.ResourceRequirements `json:"exporter,omitempty"` Coordinator *core.ResourceRequirements `json:"coordinator,omitempty"` } @@ -143,6 +144,7 @@ type MongoDBCustomConfigurationSpec struct { Mongos *MongoDBCustomConfiguration `json:"mongos,omitempty"` ConfigServer *MongoDBCustomConfiguration `json:"configServer,omitempty"` Shard *MongoDBCustomConfiguration `json:"shard,omitempty"` + Arbiter *MongoDBCustomConfiguration `json:"arbiter,omitempty"` } type MongoDBCustomConfiguration struct { diff --git a/apis/ops/v1alpha1/openapi_generated.go b/apis/ops/v1alpha1/openapi_generated.go index 14ce5a14a8..5b58c2a4de 100644 --- a/apis/ops/v1alpha1/openapi_generated.go +++ b/apis/ops/v1alpha1/openapi_generated.go @@ -22282,6 +22282,11 @@ func schema_apimachinery_apis_ops_v1alpha1_MongoDBCustomConfigurationSpec(ref co Ref: ref("kubedb.dev/apimachinery/apis/ops/v1alpha1.MongoDBCustomConfiguration"), }, }, + "arbiter": { + SchemaProps: spec.SchemaProps{ + Ref: ref("kubedb.dev/apimachinery/apis/ops/v1alpha1.MongoDBCustomConfiguration"), + }, + }, }, }, }, @@ -22655,6 +22660,11 @@ func schema_apimachinery_apis_ops_v1alpha1_MongoDBVerticalScalingSpec(ref common Ref: ref("k8s.io/api/core/v1.ResourceRequirements"), }, }, + "arbiter": { + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.ResourceRequirements"), + }, + }, "exporter": { SchemaProps: spec.SchemaProps{ Ref: ref("k8s.io/api/core/v1.ResourceRequirements"), diff --git a/apis/ops/v1alpha1/type.go b/apis/ops/v1alpha1/type.go index b83ed0b6b6..8fca56fba8 100644 --- a/apis/ops/v1alpha1/type.go +++ b/apis/ops/v1alpha1/type.go @@ -85,14 +85,15 @@ const ( ScaleUpConfigServer = "ScaleUpConfigServer " ScaleMongos = "ScaleMongos" ReconfigureReplicaset = "ReconfigureReplicaset" + ReconfigureStandalone = "ReconfigureStandalone" ReconfigureMongos = "ReconfigureMongos" ReconfigureShard = "ReconfigureShard" ReconfigureConfigServer = "ReconfigureConfigServer" + ReconfigureArbiter = "ReconfigureArbiter" UpdateStandaloneImage = "UpdateStandaloneImage" UpdateStandaloneResources = "UpdateStandaloneResources" ScaleDownStandalone = "ScaleDownStandalone" ScaleUpStandalone = "ScaleUpStandalone" - ReconfigureStandalone = "ReconfigureStandalone" StandaloneVolumeExpansion = "StandaloneVolumeExpansion" ReplicasetVolumeExpansion = "ReplicasetVolumeExpansion" ShardVolumeExpansion = "ShardVolumeExpansion" @@ -102,6 +103,7 @@ const ( RestartMongos = "RestartMongos" RestartConfigServer = "RestartConfigServer" RestartShard = "RestartShard" + RestartArbiter = "RestartArbiter" DeleteStatefulSets = "DeleteStatefulSets" DatabaseReady = "DatabaseReady" diff --git a/apis/ops/v1alpha1/zz_generated.deepcopy.go b/apis/ops/v1alpha1/zz_generated.deepcopy.go index df528b01ec..8738fa26a8 100644 --- a/apis/ops/v1alpha1/zz_generated.deepcopy.go +++ b/apis/ops/v1alpha1/zz_generated.deepcopy.go @@ -1472,6 +1472,11 @@ func (in *MongoDBCustomConfigurationSpec) DeepCopyInto(out *MongoDBCustomConfigu *out = new(MongoDBCustomConfiguration) (*in).DeepCopyInto(*out) } + if in.Arbiter != nil { + in, out := &in.Arbiter, &out.Arbiter + *out = new(MongoDBCustomConfiguration) + (*in).DeepCopyInto(*out) + } return } @@ -1748,6 +1753,11 @@ func (in *MongoDBVerticalScalingSpec) DeepCopyInto(out *MongoDBVerticalScalingSp *out = new(v1.ResourceRequirements) (*in).DeepCopyInto(*out) } + if in.Arbiter != nil { + in, out := &in.Arbiter, &out.Arbiter + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } if in.Exporter != nil { in, out := &in.Exporter, &out.Exporter *out = new(v1.ResourceRequirements) diff --git a/crds/kubedb.com_mongodbs.yaml b/crds/kubedb.com_mongodbs.yaml index 5759a7db2e..5531c2a8fd 100644 --- a/crds/kubedb.com_mongodbs.yaml +++ b/crds/kubedb.com_mongodbs.yaml @@ -112,6 +112,1504 @@ spec: type: object type: object type: object + arbiter: + nullable: true + properties: + configSecret: + properties: + name: + type: string + type: object + podTemplate: + properties: + controller: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + 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 + namespaceSelector: + 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 + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + 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 + namespaceSelector: + 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 + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + 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 + namespaceSelector: + 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 + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + 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 + namespaceSelector: + 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 + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + args: + items: + type: string + type: array + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + searches: + items: + type: string + type: array + type: object + dnsPolicy: + type: string + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + initContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + 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 + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + 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 + schedulerName: + type: string + securityContext: + properties: + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + runAsUserName: + type: string + type: object + type: object + serviceAccountName: + type: string + shareProcessNamespace: + type: boolean + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + 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 + maxSkew: + format: int32 + type: integer + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + type: object + type: object + type: object authSecret: properties: name: diff --git a/crds/ops.kubedb.com_mongodbopsrequests.yaml b/crds/ops.kubedb.com_mongodbopsrequests.yaml index ea5164d689..f04bffbc10 100644 --- a/crds/ops.kubedb.com_mongodbopsrequests.yaml +++ b/crds/ops.kubedb.com_mongodbopsrequests.yaml @@ -44,6 +44,22 @@ spec: properties: configuration: properties: + arbiter: + properties: + applyConfig: + additionalProperties: + type: string + type: object + configSecret: + properties: + name: + type: string + type: object + inlineConfig: + type: string + removeCustomConfig: + type: boolean + type: object configServer: properties: applyConfig: @@ -297,6 +313,25 @@ spec: type: object verticalScaling: properties: + arbiter: + 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 configServer: properties: limits: diff --git a/openapi/swagger.json b/openapi/swagger.json index b83dd4bf40..f1b08d01a4 100644 --- a/openapi/swagger.json +++ b/openapi/swagger.json @@ -30284,6 +30284,20 @@ } } }, + "dev.kubedb.apimachinery.apis.kubedb.v1alpha2.MongoArbiterNode": { + "type": "object", + "properties": { + "configSecret": { + "description": "ConfigSecret is an optional field to provide custom configuration file for database (i.e mongod.cnf). If specified, this file will be used as configuration file otherwise default configuration file will be used.", + "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" + }, + "podTemplate": { + "description": "PodTemplate is an optional configuration for pods used to expose database", + "default": {}, + "$ref": "#/definitions/xyz.kmodules.offshoot-api.api.v1.PodTemplateSpec" + } + } + }, "dev.kubedb.apimachinery.apis.kubedb.v1alpha2.MongoDB": { "type": "object", "properties": { @@ -30500,6 +30514,10 @@ "description": "AllowedSchemas defines the types of database schemas that MAY refer to a database instance and the trusted namespaces where those schema resources MAY be present.", "$ref": "#/definitions/dev.kubedb.apimachinery.apis.kubedb.v1alpha2.AllowedConsumers" }, + "arbiter": { + "description": "Mongo Arbiter component of mongodb. More info: https://docs.mongodb.com/manual/core/replica-set-arbiter/", + "$ref": "#/definitions/dev.kubedb.apimachinery.apis.kubedb.v1alpha2.MongoArbiterNode" + }, "authSecret": { "description": "Database authentication secret", "$ref": "#/definitions/io.k8s.api.core.v1.LocalObjectReference" @@ -32648,6 +32666,9 @@ "dev.kubedb.apimachinery.apis.ops.v1alpha1.MongoDBCustomConfigurationSpec": { "type": "object", "properties": { + "arbiter": { + "$ref": "#/definitions/dev.kubedb.apimachinery.apis.ops.v1alpha1.MongoDBCustomConfiguration" + }, "configServer": { "$ref": "#/definitions/dev.kubedb.apimachinery.apis.ops.v1alpha1.MongoDBCustomConfiguration" }, @@ -32872,6 +32893,9 @@ "description": "MongoDBVerticalScalingSpec is the spec for mongodb vertical scaling", "type": "object", "properties": { + "arbiter": { + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" + }, "configServer": { "$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements" }, diff --git a/pkg/controller/lib.go b/pkg/controller/lib.go index 27bf2d75be..06dc427912 100644 --- a/pkg/controller/lib.go +++ b/pkg/controller/lib.go @@ -39,35 +39,16 @@ func (c *Controller) SyncStatefulSetPodDisruptionBudget(sts *apps.StatefulSet) e if sts == nil { return nil } - pdbRef := metav1.ObjectMeta{ - Name: sts.Name, - Namespace: sts.Namespace, - } // CleanUp PDB for statefulSet with replica 1 if *sts.Spec.Replicas <= 1 { - err := c.Client.PolicyV1beta1().PodDisruptionBudgets(pdbRef.Namespace).Delete(context.TODO(), pdbRef.Name, metav1.DeleteOptions{}) + // pdb name & namespace is same as the corresponding statefulSet's name & namespace. + err := c.Client.PolicyV1beta1().PodDisruptionBudgets(sts.Namespace).Delete(context.TODO(), sts.Name, metav1.DeleteOptions{}) if !kerr.IsNotFound(err) { return err } - } else { - r := int32(math.Max(1, math.Floor((float64(*sts.Spec.Replicas)-1.0)/2.0))) - maxUnavailable := &intstr.IntOrString{IntVal: r} - - owner := metav1.NewControllerRef(sts, apps.SchemeGroupVersion.WithKind("StatefulSet")) - _, _, err := policy_util.CreateOrPatchPodDisruptionBudget(context.TODO(), c.Client, pdbRef, - func(in *policyv1beta1.PodDisruptionBudget) *policyv1beta1.PodDisruptionBudget { - in.Labels = sts.Labels - core_util.EnsureOwnerReference(&in.ObjectMeta, owner) - in.Spec.Selector = &metav1.LabelSelector{ - MatchLabels: sts.Spec.Selector.MatchLabels, - } - in.Spec.MaxUnavailable = maxUnavailable - in.Spec.MinAvailable = nil - return in - }, metav1.PatchOptions{}) - return err + return nil } - return nil + return c.SyncStatefulSetPDBWithCustomLabelSelectors(sts, *sts.Spec.Replicas, sts.Labels, sts.Spec.Selector.MatchLabels) } // Deprecated: CreateStatefulSetPodDisruptionBudget is deprecated. Use SyncStatefulSetPodDisruptionBudget instead. @@ -96,6 +77,33 @@ func (c *Controller) CreateStatefulSetPodDisruptionBudget(sts *apps.StatefulSet) return err } +func (c *Controller) SyncStatefulSetPDBWithCustomLabelSelectors(sts *apps.StatefulSet, replicas int32, labels map[string]string, matchLabelSelectors map[string]string) error { + if sts == nil { + return nil + } + pdbRef := metav1.ObjectMeta{ + Name: sts.Name, + Namespace: sts.Namespace, + } + + r := int32(math.Max(1, math.Floor(float64(replicas-1)/2.0))) + maxUnavailable := &intstr.IntOrString{IntVal: r} + + owner := metav1.NewControllerRef(sts, apps.SchemeGroupVersion.WithKind("StatefulSet")) + _, _, err := policy_util.CreateOrPatchPodDisruptionBudget(context.TODO(), c.Client, pdbRef, + func(in *policyv1beta1.PodDisruptionBudget) *policyv1beta1.PodDisruptionBudget { + in.Labels = labels + core_util.EnsureOwnerReference(&in.ObjectMeta, owner) + in.Spec.Selector = &metav1.LabelSelector{ + MatchLabels: matchLabelSelectors, + } + in.Spec.MaxUnavailable = maxUnavailable + in.Spec.MinAvailable = nil + return in + }, metav1.PatchOptions{}) + return err +} + func (c *Controller) CreateDeploymentPodDisruptionBudget(deployment *apps.Deployment) error { owner := metav1.NewControllerRef(deployment, apps.SchemeGroupVersion.WithKind("Deployment"))