diff --git a/api/v2/cassandracluster_types.go b/api/v2/cassandracluster_types.go index ce8f02fe..7adf5830 100644 --- a/api/v2/cassandracluster_types.go +++ b/api/v2/cassandracluster_types.go @@ -815,8 +815,21 @@ type CassandraClusterSpec struct { // +optional ShareProcessNamespace *bool `json:"shareProcessNamespace,omitempty" protobuf:"varint,27,opt,name=shareProcessNamespace"` - BackRestSidecar *BackRestSidecar `json:"backRestSidecar,omitempty"` - ServiceAccountName string `json:"serviceAccountName,omitempty"` + BackRestSidecar *BackRestSidecar `json:"backRestSidecar,omitempty"` + ServiceAccountName string `json:"serviceAccountName,omitempty"` + JMXConfiguration *JMXConfiguration `json:"jmxConfiguration,omitempty"` +} + +// JMXConfiguration defines Cassandra JMX variables configuration +type JMXConfiguration struct { + // Flag to tell that JMX remote is enabled + // +kubebuilder:default:=false + JMXRemote bool `json:"jmxRemoteEnable,omitempty"` + // JMX Remote port number + // +kubebuilder:default:=7199 + JMXRemotePort int `json:"jmxRemotePort,omitempty"` + JXMRemoteSSL bool `json:"jmxRemoteSSL,omitempty"` + JMXRemoteAuthenticate bool `json:"jmxRemoteAuthenticate,omitempty"` } // StorageConfig defines additional storage configurations diff --git a/api/v2/zz_generated.deepcopy.go b/api/v2/zz_generated.deepcopy.go index 007f7034..bafa8f3e 100644 --- a/api/v2/zz_generated.deepcopy.go +++ b/api/v2/zz_generated.deepcopy.go @@ -316,6 +316,11 @@ func (in *CassandraClusterSpec) DeepCopyInto(out *CassandraClusterSpec) { *out = new(BackRestSidecar) (*in).DeepCopyInto(*out) } + if in.JMXConfiguration != nil { + in, out := &in.JMXConfiguration, &out.JMXConfiguration + *out = new(JMXConfiguration) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CassandraClusterSpec. @@ -608,6 +613,21 @@ func (in *FailureCause) DeepCopy() *FailureCause { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JMXConfiguration) DeepCopyInto(out *JMXConfiguration) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JMXConfiguration. +func (in *JMXConfiguration) DeepCopy() *JMXConfiguration { + if in == nil { + return nil + } + out := new(JMXConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodLastOperation) DeepCopyInto(out *PodLastOperation) { *out = *in diff --git a/config/crd/bases/db.orange.com_cassandraclusters.yaml b/config/crd/bases/db.orange.com_cassandraclusters.yaml index 37e62972..63e31663 100644 --- a/config/crd/bases/db.orange.com_cassandraclusters.yaml +++ b/config/crd/bases/db.orange.com_cassandraclusters.yaml @@ -236,6 +236,22 @@ spec: imagepullpolicy: description: ImagePullPolicy define the pull policy for C* docker image type: string + jmxConfiguration: + description: JMXConfiguration defines Cassandra JMX variables configuration + type: object + properties: + jmxRemoteAuthenticate: + type: boolean + jmxRemoteEnable: + description: Flag to tell that JMX remote is enabled + type: boolean + default: false + jmxRemotePort: + description: JMX Remote port number + type: integer + default: 7199 + jmxRemoteSSL: + type: boolean keyspaceCleanupThreads: description: |- Number of jobs (threads) for keyspace cleanup command. diff --git a/controllers/cassandracluster/generator.go b/controllers/cassandracluster/generator.go index 0bf68e04..b5e1740d 100644 --- a/controllers/cassandracluster/generator.go +++ b/controllers/cassandracluster/generator.go @@ -17,6 +17,7 @@ package cassandracluster import ( "encoding/json" "fmt" + "reflect" "github.com/Jeffail/gabs" "github.com/banzaicloud/k8s-objectmatcher/patch" @@ -65,6 +66,7 @@ const ( cassandraConfigMapName = "cassandra-config" defaultBackRestPort = 4567 + jvmOptsName = "JVM_OPTS" ) type containerType int @@ -76,6 +78,15 @@ const ( backrestContainer ) +// JMXConfigurationMap +// Create a JMX Configuration map to convert values from CR to how they look like as env vars +var JMXConfigurationMap = map[string]string{ + "JMXRemote": "-Dcom.sun.management.jmxremote=", + "JMXRemotePort": "-Dcom.sun.management.jmxremote.port=", + "JXMRemoteSSL": "-Dcom.sun.management.jmxremote.ssl=", + "JMXRemoteAuthenticate": "-Dcom.sun.management.jmxremote.authenticate=", +} + type NodeConfig map[string]map[string]interface{} func generateCassandraService(cc *api.CassandraCluster, labels map[string]string, @@ -293,6 +304,21 @@ func generateVolumeClaimTemplate(cc *api.CassandraCluster, labels map[string]str return pvc, nil } +func generateJMXConfiguration(jmxConf api.JMXConfiguration) v1.EnvVar { + var jmxEnvVar v1.EnvVar + var jmxParam string + values := reflect.ValueOf(jmxConf) + types := reflect.TypeOf(jmxConf) + for i := 0; i < values.NumField(); i++ { + fieldName := types.Field(i).Name + fieldValue := values.Field(i).Interface() + param := JMXConfigurationMap[fieldName] + fmt.Sprintf("%v", fieldValue) + " " + jmxParam += param + } + jmxEnvVar = v1.EnvVar{Name: jvmOptsName, Value: jmxParam} + return jmxEnvVar +} + func generateCassandraStatefulSet(cc *api.CassandraCluster, status *api.CassandraClusterStatus, dcName string, dcRackName string, labels map[string]string, nodeSelector map[string]string, ownerRefs []metav1.OwnerReference) (*appsv1.StatefulSet, error) { @@ -932,6 +958,10 @@ func createCassandraContainer(cc *api.CassandraCluster, status *api.CassandraClu Value: "-Dcom.sun.jndi.rmiURLParsing=legacy", }) + if cc.Spec.JMXConfiguration != nil { + jmxEnvVariable := generateJMXConfiguration(*cc.Spec.JMXConfiguration) + cassandraEnv = append(cassandraEnv, jmxEnvVariable) + } cassandraContainer := v1.Container{ Name: cassandraContainerName, Image: cc.Spec.CassandraImage, diff --git a/controllers/cassandracluster/generator_test.go b/controllers/cassandracluster/generator_test.go index e3490d6d..1ff426e3 100644 --- a/controllers/cassandracluster/generator_test.go +++ b/controllers/cassandracluster/generator_test.go @@ -691,6 +691,7 @@ func checkVarEnv(t *testing.T, containers []v1.Container, cc *api.CassandraClust cassieResources := cc.Spec.Resources initContainerEnvVar := initContainerEnvVar(cc, &cc.Status, cassieResources, dcRackName) bootstrapContainerEnvVar := bootstrapContainerEnvVar(cc, &cc.Status) + jmxEnvVar := generateJMXConfiguration(*cc.Spec.JMXConfiguration) assert := assert.New(t) @@ -755,6 +756,7 @@ func checkVarEnv(t *testing.T, containers []v1.Container, cc *api.CassandraClust }, } assert.Contains(container.Env, podIP) + assert.Contains(container.Env, jmxEnvVar) checkInitContainerVarEnv(t, initContainerEnvVar, vars) } diff --git a/controllers/cassandracluster/testdata/cassandracluster-2DC.yaml b/controllers/cassandracluster/testdata/cassandracluster-2DC.yaml index be380ffc..ae4ec185 100644 --- a/controllers/cassandracluster/testdata/cassandracluster-2DC.yaml +++ b/controllers/cassandracluster/testdata/cassandracluster-2DC.yaml @@ -31,6 +31,11 @@ spec: nodesPerRacks: 1 cassandraImage: cassandra:3.11.7 restartCountBeforePodDeletion: 3 + jmxConfiguration: + jmxRemoteEnable: false + jmxRemotePort: 7199 + jmxRemoteSSL: false + jmxRemoteAuthenticate: false imagePullSecret: name: advisedev # To authenticate on docker registry rollingPartition: 0