Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api/v1/marklogiccluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ type MarklogicClusterSpec struct {
// +kubebuilder:validation:XValidation:rule="self == oldSelf", message="ServiceAccountName can not be changed"
// The name of the service account to assigned to the MarkLogic pods
ServiceAccountName string `json:"serviceAccountName,omitempty"`
// +kubebuilder:default:=false
AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty"`
// +kubebuilder:default:={enabled: true, size: "10Gi"}
Persistence *Persistence `json:"persistence,omitempty"`
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
Expand Down
16 changes: 9 additions & 7 deletions api/v1/marklogicgroup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@ type MarklogicGroupSpec struct {
// +kubebuilder:default:="progressofficial/marklogic-db:11.3.0-ubi-rootless"
Image string `json:"image"`
// +kubebuilder:default:="IfNotPresent"
ImagePullPolicy string `json:"imagePullPolicy,omitempty"`
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
Auth *AdminAuth `json:"auth,omitempty"`
ServiceAccountName string `json:"serviceAccountName,omitempty"`
Persistence *Persistence `json:"persistence,omitempty"`
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`
ImagePullPolicy string `json:"imagePullPolicy,omitempty"`
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
Auth *AdminAuth `json:"auth,omitempty"`
ServiceAccountName string `json:"serviceAccountName,omitempty"`
// +kubebuilder:default:=false
AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty"`
Persistence *Persistence `json:"persistence,omitempty"`
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`
// +kubebuilder:validation:Enum=OnDelete;RollingUpdate
// +kubebuilder:default:="OnDelete"
UpdateStrategy appsv1.StatefulSetUpdateStrategyType `json:"updateStrategy,omitempty"`
Expand Down
10 changes: 10 additions & 0 deletions api/v1/zz_generated.deepcopy.go

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

Original file line number Diff line number Diff line change
Expand Up @@ -3260,6 +3260,9 @@ spec:
walletPassword:
type: string
type: object
automountServiceAccountToken:
default: false
type: boolean
clusterDomain:
default: cluster.local
type: string
Expand Down
3 changes: 3 additions & 0 deletions config/crd/bases/marklogic.progress.com_marklogicgroups.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3265,6 +3265,9 @@ spec:
walletPassword:
type: string
type: object
automountServiceAccountToken:
default: false
type: boolean
bootstrapHost:
type: string
clusterDomain:
Expand Down
2 changes: 1 addition & 1 deletion config/samples/complete.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ metadata:
namespace: prod
annotations: {}
spec:
image: "progressofficial/marklogic-db:11.3.1-ubi-rootless-2.1.1"
image: "progressofficial/marklogic-db:11.3.1-ubi-rootless-2.2.1"
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: regcred
Expand Down
2 changes: 1 addition & 1 deletion config/samples/minimal-production.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ metadata:
name: ml-cluster
namespace: prod
spec:
image: "progressofficial/marklogic-db:11.3.1-ubi-rootless-2.1.1"
image: "progressofficial/marklogic-db:11.3.1-ubi-rootless-2.2.1"
## It is recommended to use Kubernetes secrets to store the admin credentials
## To create a secret, run the following command in the same namespace as the CR:
## kubectl create secret generic admincreds --from-literal=username=admin --from-literal=password=admin
Expand Down
11 changes: 2 additions & 9 deletions config/samples/quick-start.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,17 @@ metadata:
name: single-node
annotations: {}
spec:
image: "progressofficial/marklogic-db:11.3.0-ubi-rootless"
image: "progressofficial/marklogic-db:11.3.1-ubi-rootless-2.2.1"
## It is recommended to use Kubernetes secrets to store the admin credentials
## To create a secret, run the following command in the same namespace as the CR:
## kubectl create secret generic admincreds --from-literal=username=admin --from-literal=password=admin
## If you do not provide the admin credentials, the operator will generate a secret for you containing admin credentials
persistence:
enabled: true
enabled: false
size: 10Gi
markLogicGroups:
- replicas: 1
name: node
groupConfig:
name: node
resources:
requests:
memory: "4Gi"
cpu: 2000m
limits:
memory: "4Gi"
cpu: 2000m
isBootstrap: true
6 changes: 6 additions & 0 deletions pkg/k8sutil/marklogicServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type MarkLogicGroupParameters struct {
Replicas *int32
Name string
ServiceAccountName string
AutomountServiceAccountToken *bool
Labels map[string]string
Annotations map[string]string
GroupConfig *marklogicv1.GroupConfig
Expand Down Expand Up @@ -124,6 +125,7 @@ func (cc *ClusterContext) GenerateMarkLogicGroupDef(cr *marklogicv1.MarklogicClu
GroupConfig: params.GroupConfig,
Auth: params.Auth,
ServiceAccountName: params.ServiceAccountName,
AutomountServiceAccountToken: params.AutomountServiceAccountToken,
Image: params.Image,
Labels: params.Labels,
Annotations: params.Annotations,
Expand Down Expand Up @@ -261,6 +263,9 @@ func generateMarkLogicClusterParams(cr *marklogicv1.MarklogicCluster) *MarkLogic
}

func generateMarkLogicGroupParams(cr *marklogicv1.MarklogicCluster, index int, clusterParams *MarkLogicClusterParameters) *MarkLogicGroupParameters {
// Always enforce automountServiceAccountToken to false for security
falseValue := false

markLogicGroupParameters := &MarkLogicGroupParameters{
Comment on lines +266 to 269
Copy link
Preview

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider using a package-level constant for the false value instead of declaring it locally in each function. This would improve consistency and make the security requirement more explicit.

Copilot uses AI. Check for mistakes.

Replicas: cr.Spec.MarkLogicGroups[index].Replicas,
Name: cr.Spec.MarkLogicGroups[index].Name,
Expand All @@ -273,6 +278,7 @@ func generateMarkLogicGroupParams(cr *marklogicv1.MarklogicCluster, index int, c
ImagePullSecrets: clusterParams.ImagePullSecrets,
Auth: clusterParams.Auth,
ServiceAccountName: clusterParams.ServiceAccountName,
AutomountServiceAccountToken: &falseValue, // Always false for security
License: clusterParams.License,
Persistence: clusterParams.Persistence,
TerminationGracePeriodSeconds: clusterParams.TerminationGracePeriodSeconds,
Expand Down
8 changes: 8 additions & 0 deletions pkg/k8sutil/statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type statefulSetParameters struct {
ImagePullSecrets []corev1.LocalObjectReference
AdditionalVolumeClaimTemplates *[]corev1.PersistentVolumeClaim
ServiceAccountName string
AutomountServiceAccountToken *bool
}

type containerParameters struct {
Expand Down Expand Up @@ -238,6 +239,9 @@ func generateStatefulSetsDef(stsMeta metav1.ObjectMeta, params statefulSetParame
if params.ServiceAccountName != "" {
statefulSet.Spec.Template.Spec.ServiceAccountName = params.ServiceAccountName
}
if params.AutomountServiceAccountToken != nil {
statefulSet.Spec.Template.Spec.AutomountServiceAccountToken = params.AutomountServiceAccountToken
}
if containerParams.Tls != nil && containerParams.Tls.EnableOnDefaultAppServers {
copyCertsVM := []corev1.VolumeMount{
{
Expand Down Expand Up @@ -349,10 +353,14 @@ func generateContainerDef(name string, containerParams containerParameters) []co
}

func generateStatefulSetsParams(cr *marklogicv1.MarklogicGroup) statefulSetParameters {
// Always enforce automountServiceAccountToken to false for security
falseValue := false

params := statefulSetParameters{
Comment on lines +356 to 359
Copy link
Preview

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider using a package-level constant for the false value instead of declaring it locally in each function. This would improve consistency and make the security requirement more explicit.

Copilot uses AI. Check for mistakes.

Replicas: cr.Spec.Replicas,
Name: cr.Spec.Name,
ServiceAccountName: cr.Spec.ServiceAccountName,
AutomountServiceAccountToken: &falseValue, // Always false for security
TerminationGracePeriodSeconds: cr.Spec.TerminationGracePeriodSeconds,
UpdateStrategy: cr.Spec.UpdateStrategy,
NodeSelector: cr.Spec.NodeSelector,
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/2_marklogic_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ func TestMarklogicCluster(t *testing.T) {
}
// Exponential backoff: 1s, 2s, 4s, 8s, 16s
time.Sleep(time.Duration(1<<(attempt-1)) * time.Second)
}
}
t.Logf("Query datasource response: %s", output)
// Verify MarkLogic logs in Grafana using Loki and Fluent Bit
if strings.Contains(string(output), "Starting MarkLogic Server") {
Expand Down