From a699b95fa9a11553e0f4df491e8fd5192d115cfb Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 02:50:43 +0000 Subject: [PATCH 01/12] feat(api): remove stale CredentialSecretVersion and ServiceAccount from IngestorClusterStatus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CredentialSecretVersion and ServiceAccount status fields are no longer needed. The new event-driven ConfigMap approach (CSPL-4556) uses controller watches (Queue CR, ObjectStorage CR, Secret) to trigger reconcile and splctrl.ApplyConfigMap as the idempotency gate. The ingestorQueueConfigRev pod annotation replaces the credential version change signal. - Remove CredentialSecretVersion and ServiceAccount from IngestorClusterStatus - Remove scale-up credential reset in ApplyIngestorCluster - Remove PhaseReady credential/serviceAccount comparison and REST restart block - Fix namespaceScopedSecret → _ (no longer passed to pod manager) - Remove CredentialSecretVersion from test fixture - Regenerate CRD YAML via make manifests CSPL-4556 --- api/v4/ingestorcluster_types.go | 5 --- ...nterprise.splunk.com_ingestorclusters.yaml | 10 ----- pkg/splunk/enterprise/ingestorcluster.go | 38 +------------------ pkg/splunk/enterprise/ingestorcluster_test.go | 5 +-- 4 files changed, 3 insertions(+), 55 deletions(-) diff --git a/api/v4/ingestorcluster_types.go b/api/v4/ingestorcluster_types.go index 4e206e76a..a3e2d66c7 100644 --- a/api/v4/ingestorcluster_types.go +++ b/api/v4/ingestorcluster_types.go @@ -76,11 +76,6 @@ type IngestorClusterStatus struct { // Auxillary message describing CR status Message string `json:"message"` - // Credential secret version to track changes to the secret and trigger rolling restart of indexer cluster peers when the secret is updated - CredentialSecretVersion string `json:"credentialSecretVersion,omitempty"` - - // Service account to track changes to the service account and trigger rolling restart of indexer cluster peers when the service account is updated - ServiceAccount string `json:"serviceAccount,omitempty"` } // +kubebuilder:object:root=true diff --git a/config/crd/bases/enterprise.splunk.com_ingestorclusters.yaml b/config/crd/bases/enterprise.splunk.com_ingestorclusters.yaml index 380109fb8..b27799d39 100644 --- a/config/crd/bases/enterprise.splunk.com_ingestorclusters.yaml +++ b/config/crd/bases/enterprise.splunk.com_ingestorclusters.yaml @@ -4612,11 +4612,6 @@ spec: description: App Framework version info for future use type: integer type: object - credentialSecretVersion: - description: Credential secret version to track changes to the secret - and trigger rolling restart of indexer cluster peers when the secret - is updated - type: string message: description: Auxillary message describing CR status type: string @@ -4647,11 +4642,6 @@ spec: selector: description: Selector for pods used by HorizontalPodAutoscaler type: string - serviceAccount: - description: Service account to track changes to the service account - and trigger rolling restart of indexer cluster peers when the service - account is updated - type: string telAppInstalled: description: Telemetry App installation flag type: boolean diff --git a/pkg/splunk/enterprise/ingestorcluster.go b/pkg/splunk/enterprise/ingestorcluster.go index b0f866413..cc5b87a94 100644 --- a/pkg/splunk/enterprise/ingestorcluster.go +++ b/pkg/splunk/enterprise/ingestorcluster.go @@ -70,10 +70,6 @@ func ApplyIngestorCluster(ctx context.Context, client client.Client, cr *enterpr // Update the CR Status defer updateCRStatus(ctx, client, cr, &err) - if cr.Status.Replicas < cr.Spec.Replicas { - cr.Status.CredentialSecretVersion = "0" - cr.Status.ServiceAccount = "" - } cr.Status.Replicas = cr.Spec.Replicas // If needed, migrate the app framework status @@ -97,7 +93,7 @@ func ApplyIngestorCluster(ctx context.Context, client client.Client, cr *enterpr cr.Status.Selector = fmt.Sprintf("app.kubernetes.io/instance=splunk-%s-ingestor", cr.GetName()) // Create or update general config resources - namespaceScopedSecret, err := ApplySplunkConfig(ctx, client, cr, cr.Spec.CommonSplunkSpec, SplunkIngestor) + _, err = ApplySplunkConfig(ctx, client, cr, cr.Spec.CommonSplunkSpec, SplunkIngestor) if err != nil { scopedLog.Error(err, "create or update general config failed", "error", err.Error()) eventPublisher.Warning(ctx, "ApplySplunkConfig", fmt.Sprintf("create or update general config failed with error %s", err.Error())) @@ -209,38 +205,6 @@ func ApplyIngestorCluster(ctx context.Context, client client.Client, cr *enterpr // No need to requeue if everything is ready if cr.Status.Phase == enterpriseApi.PhaseReady { - qosCfg, err := ResolveQueueAndObjectStorage(ctx, client, cr, cr.Spec.QueueRef, cr.Spec.ObjectStorageRef, cr.Spec.ServiceAccount) - if err != nil { - scopedLog.Error(err, "Failed to resolve Queue/ObjectStorage config") - return result, err - } - - secretChanged := cr.Status.CredentialSecretVersion != qosCfg.Version - serviceAccountChanged := cr.Status.ServiceAccount != cr.Spec.ServiceAccount - - // If queue is updated - if secretChanged || serviceAccountChanged { - mgr := newIngestorClusterPodManager(scopedLog, cr, namespaceScopedSecret, splclient.NewSplunkClient, client) - err = mgr.updateIngestorConfFiles(ctx, cr, &qosCfg.Queue, &qosCfg.OS, qosCfg.AccessKey, qosCfg.SecretKey, client) - if err != nil { - eventPublisher.Warning(ctx, "ApplyIngestorCluster", fmt.Sprintf("Failed to update conf file for Queue/Pipeline config change after pod creation: %s", err.Error())) - scopedLog.Error(err, "Failed to update conf file for Queue/Pipeline config change after pod creation") - return result, err - } - - for i := int32(0); i < cr.Spec.Replicas; i++ { - ingClient := mgr.getClient(ctx, i) - err = ingClient.RestartSplunk() - if err != nil { - return result, err - } - scopedLog.Info("Restarted splunk", "ingestor", i) - } - - cr.Status.CredentialSecretVersion = qosCfg.Version - cr.Status.ServiceAccount = cr.Spec.ServiceAccount - } - // Upgrade fron automated MC to MC CRD namespacedName := types.NamespacedName{Namespace: cr.GetNamespace(), Name: GetSplunkStatefulsetName(SplunkMonitoringConsole, cr.GetNamespace())} err = splctrl.DeleteReferencesToAutomatedMCIfExists(ctx, client, cr, namespacedName) diff --git a/pkg/splunk/enterprise/ingestorcluster_test.go b/pkg/splunk/enterprise/ingestorcluster_test.go index e96002372..d643ff415 100644 --- a/pkg/splunk/enterprise/ingestorcluster_test.go +++ b/pkg/splunk/enterprise/ingestorcluster_test.go @@ -615,9 +615,8 @@ func TestUpdateIngestorConfFiles(t *testing.T) { }, }, Status: enterpriseApi.IngestorClusterStatus{ - Replicas: 3, - ReadyReplicas: 3, - CredentialSecretVersion: "123", + Replicas: 3, + ReadyReplicas: 3, }, } From d96286b35dd4ae18833076f7619550e1594d3df4 Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 02:51:32 +0000 Subject: [PATCH 02/12] feat(names): add ingestor queue config naming constants and GetIngestorQueueConfigMapName Add five package-level constants and one exported naming function to support the ConfigMap-based ingestor queue configuration delivery: - ingestorQueueConfigAppName: Splunk app directory "100-sok-ingestorcluster" - ingestorQueueConfigTemplateStr: ConfigMap name pattern "splunk--ingestor-queue-config" - ingestorQueueConfigRevAnnotation: pod annotation key "ingestorQueueConfigRev" - ingestorQueueConfigMountPath: "/mnt/splunk-queue-config" - commandForIngestorQueueConfig: init container bash command (mkdir + ln -sfn + cp local.meta) - GetIngestorQueueConfigMapName(crName): formats ConfigMap name CSPL-4554 --- pkg/splunk/enterprise/names.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/pkg/splunk/enterprise/names.go b/pkg/splunk/enterprise/names.go index 623f361f8..a6e30a5c1 100644 --- a/pkg/splunk/enterprise/names.go +++ b/pkg/splunk/enterprise/names.go @@ -218,6 +218,30 @@ access = read : [ * ], write : [ admin ] telLicenseInfoKey = "license_info" managerConfigMapTemplateStr = "%smanager-config" + + // ingestorQueueConfigAppName is the Splunk app directory name for ingestor queue config + ingestorQueueConfigAppName = "100-sok-ingestorcluster" + + // ingestorQueueConfigTemplateStr is the ConfigMap name pattern: splunk--ingestor-queue-config + ingestorQueueConfigTemplateStr = "splunk-%s-ingestor-queue-config" + + // ingestorQueueConfigRevAnnotation is the pod annotation key set to ConfigMap ResourceVersion. + // When content changes (credentials rotate, topology changes), RV increments → annotation changes + // → Restart EPIC detects change and restarts pods (PDB-aware). reload.outputs.remote_queue=never. + ingestorQueueConfigRevAnnotation = "ingestorQueueConfigRev" + + // ingestorQueueConfigMountPath is the ConfigMap mount path inside the pod + ingestorQueueConfigMountPath = "/mnt/splunk-queue-config" + + // commandForIngestorQueueConfig is the init container shell command. + // Creates app directory, symlinks conf files from ConfigMap mount, copies local.meta + // (NOT symlinked — Splunk replaces metadata symlinks with regular files when writing stanzas). + commandForIngestorQueueConfig = "mkdir -p /opt/splk/etc/apps/" + ingestorQueueConfigAppName + "/local && " + + "mkdir -p /opt/splk/etc/apps/" + ingestorQueueConfigAppName + "/metadata && " + + "ln -sfn " + ingestorQueueConfigMountPath + "/app.conf /opt/splk/etc/apps/" + ingestorQueueConfigAppName + "/local/app.conf && " + + "ln -sfn " + ingestorQueueConfigMountPath + "/outputs.conf /opt/splk/etc/apps/" + ingestorQueueConfigAppName + "/local/outputs.conf && " + + "ln -sfn " + ingestorQueueConfigMountPath + "/default-mode.conf /opt/splk/etc/apps/" + ingestorQueueConfigAppName + "/local/default-mode.conf && " + + "cp " + ingestorQueueConfigMountPath + "/local.meta /opt/splk/etc/apps/" + ingestorQueueConfigAppName + "/metadata/local.meta" ) const ( @@ -383,3 +407,8 @@ func GetTelemetryConfigMapName(namePrefix string) string { func GetManagerConfigMapName(namePrefix string) string { return fmt.Sprintf(managerConfigMapTemplateStr, namePrefix) } + +// GetIngestorQueueConfigMapName returns the name of the ingestor queue config ConfigMap +func GetIngestorQueueConfigMapName(crName string) string { + return fmt.Sprintf(ingestorQueueConfigTemplateStr, crName) +} From 64fd43ab7af4fade84d4bcd7ee6aff6cc593a263 Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 02:56:25 +0000 Subject: [PATCH 03/12] feat(enterprise): add INI builder functions and computeIngestorConfChecksum for queue config Add five pure functions to build the ConfigMap content for the ingestor queue configuration app. These functions are side-effect-free and called by buildAndApplyIngestorQueueConfigMap in the next commit. - computeIngestorConfChecksum: SHA-256 of outputsConf+defaultModeConf stored in local.meta [app/install] so Splunk detects content changes - generateIngestorOutputsConf: builds outputs.conf reusing getQueueAndObjectStorageInputsForIngestorConfFiles; embeds credentials when non-empty (same pattern as GetSmartstoreVolumesConfig) - generateIngestorDefaultModeConf: builds default-mode.conf reusing getPipelineInputsForConfFile(false) - generateIngestorAppConf: builds app.conf with state=enabled - generateIngestorLocalMeta: builds local.meta with system access + install_source_checksum stanza CSPL-4554 --- pkg/splunk/enterprise/ingestorcluster.go | 63 ++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/pkg/splunk/enterprise/ingestorcluster.go b/pkg/splunk/enterprise/ingestorcluster.go index cc5b87a94..eb37fe0a3 100644 --- a/pkg/splunk/enterprise/ingestorcluster.go +++ b/pkg/splunk/enterprise/ingestorcluster.go @@ -16,6 +16,7 @@ package enterprise import ( "context" + "crypto/sha256" "fmt" "reflect" "strings" @@ -363,6 +364,68 @@ var newIngestorClusterPodManager = func(log logr.Logger, cr *enterpriseApi.Inges } } +// computeIngestorConfChecksum returns a SHA-256 hex digest of the combined conf content. +// Stored in local.meta so Splunk detects content changes on app load. +func computeIngestorConfChecksum(outputsConf, defaultModeConf string) string { + h := sha256.New() + h.Write([]byte(outputsConf)) + h.Write([]byte(defaultModeConf)) + return fmt.Sprintf("%x", h.Sum(nil)) +} + +// generateIngestorOutputsConf builds outputs.conf INI content. +// Reuses getQueueAndObjectStorageInputsForIngestorConfFiles for key-value pairs. +// Credentials embedded when non-empty (same pattern as GetSmartstoreVolumesConfig). +func generateIngestorOutputsConf(queue *enterpriseApi.QueueSpec, os *enterpriseApi.ObjectStorageSpec, accessKey, secretKey string) string { + kvPairs := getQueueAndObjectStorageInputsForIngestorConfFiles(queue, os, accessKey, secretKey) + var b strings.Builder + fmt.Fprintf(&b, "[remote_queue:%s]\n", queue.SQS.Name) + for _, kv := range kvPairs { + fmt.Fprintf(&b, "%s = %s\n", kv[0], kv[1]) + } + return b.String() +} + +// generateIngestorDefaultModeConf builds default-mode.conf INI content. +// Reuses getPipelineInputsForConfFile(false) for the six pipeline stanzas. +func generateIngestorDefaultModeConf() string { + pipelineInputs := getPipelineInputsForConfFile(false) + var b strings.Builder + for _, input := range pipelineInputs { + fmt.Fprintf(&b, "[%s]\n%s = %s\n\n", input[0], input[1], input[2]) + } + return b.String() +} + +// generateIngestorAppConf builds app.conf INI content. +func generateIngestorAppConf() string { + return `[install] +state = enabled +allows_disable = false + +[package] +check_for_updates = false + +[ui] +is_visible = false +is_manageable = false +label = Splunk Operator Ingestor Queue Config +description = Operator-managed queue and pipeline configuration for IngestorCluster +` +} + +// generateIngestorLocalMeta builds local.meta with system-level access and embedded checksum. +// confChecksum is SHA-256 of outputsConf+defaultModeConf — produced by computeIngestorConfChecksum. +func generateIngestorLocalMeta(confChecksum string) string { + return fmt.Sprintf(`[] +access = read : [ * ], write : [ admin ] +export = system + +[app/install] +install_source_checksum = %s +`, confChecksum) +} + // getPipelineInputsForConfFile returns a list of pipeline inputs for conf file func getPipelineInputsForConfFile(isIndexer bool) (config [][]string) { config = append(config, From b12173665acb159dd547641f04541eeb8fb93443 Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 03:15:48 +0000 Subject: [PATCH 04/12] feat(enterprise): add buildAndApplyIngestorQueueConfigMap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build and idempotently apply the ingestor queue config ConfigMap on every reconcile. splctrl.ApplyConfigMap is the idempotency gate — it skips the write and returns (false, nil) when content is unchanged, so no extra work is done on no-op reconciles triggered by the controller watches. - Takes resolved QueueOSConfig (Queue, OS, AccessKey, SecretKey) - Builds all four ConfigMap keys using the INI builder functions - Sets owner reference so ConfigMap is GC'd with the IngestorCluster CR - Returns (changed bool, error) matching splctrl.ApplyConfigMap signature CSPL-4554 --- pkg/splunk/enterprise/ingestorcluster.go | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pkg/splunk/enterprise/ingestorcluster.go b/pkg/splunk/enterprise/ingestorcluster.go index eb37fe0a3..fbdc57209 100644 --- a/pkg/splunk/enterprise/ingestorcluster.go +++ b/pkg/splunk/enterprise/ingestorcluster.go @@ -30,6 +30,7 @@ import ( splutil "github.com/splunk/splunk-operator/pkg/splunk/util" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" @@ -284,6 +285,33 @@ func validateIngestorClusterSpec(ctx context.Context, c splcommon.ControllerClie return validateCommonSplunkSpec(ctx, c, &cr.Spec.CommonSplunkSpec, cr) } +// buildAndApplyIngestorQueueConfigMap builds and idempotently applies the ingestor queue +// config ConfigMap. Returns (true, nil) when content changed, (false, nil) when unchanged. +// Called unconditionally on every reconcile — splctrl.ApplyConfigMap is the idempotency gate. +func buildAndApplyIngestorQueueConfigMap(ctx context.Context, c splcommon.ControllerClient, cr *enterpriseApi.IngestorCluster, qosCfg *QueueOSConfig) (bool, error) { + configMapName := GetIngestorQueueConfigMapName(cr.GetName()) + + outputsConf := generateIngestorOutputsConf(&qosCfg.Queue, &qosCfg.OS, qosCfg.AccessKey, qosCfg.SecretKey) + defaultModeConf := generateIngestorDefaultModeConf() + confChecksum := computeIngestorConfChecksum(outputsConf, defaultModeConf) + + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: configMapName, + Namespace: cr.GetNamespace(), + }, + Data: map[string]string{ + "app.conf": generateIngestorAppConf(), + "outputs.conf": outputsConf, + "default-mode.conf": defaultModeConf, + "local.meta": generateIngestorLocalMeta(confChecksum), + }, + } + configMap.SetOwnerReferences(append(configMap.GetOwnerReferences(), splcommon.AsOwner(cr, true))) + + return splctrl.ApplyConfigMap(ctx, c, configMap) +} + // getIngestorStatefulSet returns a Kubernetes StatefulSet object for Splunk Enterprise ingestors func getIngestorStatefulSet(ctx context.Context, client splcommon.ControllerClient, cr *enterpriseApi.IngestorCluster) (*appsv1.StatefulSet, error) { ss, err := getSplunkStatefulSet(ctx, client, cr, &cr.Spec.CommonSplunkSpec, SplunkIngestor, cr.Spec.Replicas, []corev1.EnvVar{}) From a045c11fe7925c56cfd13f70db3fd0de25032f67 Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 03:21:29 +0000 Subject: [PATCH 05/12] feat(enterprise): add setupIngestorInitContainer and update getIngestorStatefulSet Add the init container that pre-delivers queue config files before Splunk starts, enabling zero-restart first-boot configuration (CSPL-4553). setupIngestorInitContainer: - Adds ConfigMap volume (mnt-splunk-queue-config) to the pod spec - Appends init-ingestor-queue-config init container with the same security context as the existing setupInitContainer (runAsUser=41812, drop ALL, SeccompProfileTypeRuntimeDefault) - Mounts /opt/splk/etc (etc PVC or ephemeral) + ConfigMap at mount path - Runs commandForIngestorQueueConfig: mkdir + ln -sfn (conf files) + cp local.meta (cp not ln -sfn: Splunk replaces metadata symlinks with regular files) - Sets ingestorQueueConfigRev pod annotation to ConfigMap ResourceVersion so the Restart EPIC detects content changes and triggers a rolling restart getIngestorStatefulSet updated to call setupIngestorInitContainer after setupAppsStagingVolume. CSPL-4553 --- pkg/splunk/enterprise/ingestorcluster.go | 88 ++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/pkg/splunk/enterprise/ingestorcluster.go b/pkg/splunk/enterprise/ingestorcluster.go index fbdc57209..5a2c16dbf 100644 --- a/pkg/splunk/enterprise/ingestorcluster.go +++ b/pkg/splunk/enterprise/ingestorcluster.go @@ -31,6 +31,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" @@ -312,6 +313,88 @@ func buildAndApplyIngestorQueueConfigMap(ctx context.Context, c splcommon.Contro return splctrl.ApplyConfigMap(ctx, c, configMap) } +// setupIngestorInitContainer adds the queue config init container and ConfigMap volume to the +// StatefulSet pod template. The init container symlinks conf files and copies local.meta before +// Splunk starts, enabling zero-restart first-boot configuration. +func setupIngestorInitContainer(ctx context.Context, c splcommon.ControllerClient, cr *enterpriseApi.IngestorCluster, ss *appsv1.StatefulSet) error { + // Determine etc volume mount name (ephemeral vs PVC — mirrors setupInitContainer pattern) + var etcVolMntName string + if cr.Spec.CommonSplunkSpec.EtcVolumeStorageConfig.EphemeralStorage { + etcVolMntName = fmt.Sprintf(splcommon.SplunkMountNamePrefix, splcommon.EtcVolumeStorage) + } else { + etcVolMntName = fmt.Sprintf(splcommon.PvcNamePrefix, splcommon.EtcVolumeStorage) + } + + // Add ConfigMap volume to pod spec + queueConfigVolName := "mnt-splunk-queue-config" + ss.Spec.Template.Spec.Volumes = append(ss.Spec.Template.Spec.Volumes, corev1.Volume{ + Name: queueConfigVolName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: GetIngestorQueueConfigMapName(cr.GetName()), + }, + }, + }, + }) + + // Security context — same as setupInitContainer in util.go + runAsUser := int64(41812) + runAsNonRoot := true + privileged := false + + initContainer := corev1.Container{ + Name: "init-ingestor-queue-config", + Image: ss.Spec.Template.Spec.Containers[0].Image, + ImagePullPolicy: ss.Spec.Template.Spec.Containers[0].ImagePullPolicy, + Command: []string{"bash", "-c", commandForIngestorQueueConfig}, + VolumeMounts: []corev1.VolumeMount{ + {Name: etcVolMntName, MountPath: "/opt/splk/etc"}, + {Name: queueConfigVolName, MountPath: ingestorQueueConfigMountPath}, + }, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("0.25"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("512Mi"), + }, + }, + SecurityContext: &corev1.SecurityContext{ + RunAsUser: &runAsUser, + RunAsNonRoot: &runAsNonRoot, + AllowPrivilegeEscalation: &[]bool{false}[0], + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + Add: []corev1.Capability{"NET_BIND_SERVICE"}, + }, + Privileged: &privileged, + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + }, + } + ss.Spec.Template.Spec.InitContainers = append(ss.Spec.Template.Spec.InitContainers, initContainer) + + // Set ingestorQueueConfigRev annotation to ConfigMap ResourceVersion. + // When ConfigMap content changes the RV increments, the annotation changes, + // and the Restart EPIC detects the pod template diff and triggers a rolling restart. + cmRV, err := splctrl.GetConfigMapResourceVersion(ctx, c, types.NamespacedName{ + Name: GetIngestorQueueConfigMapName(cr.GetName()), + Namespace: cr.GetNamespace(), + }) + if err == nil && cmRV != "" { + if ss.Spec.Template.ObjectMeta.Annotations == nil { + ss.Spec.Template.ObjectMeta.Annotations = make(map[string]string) + } + ss.Spec.Template.ObjectMeta.Annotations[ingestorQueueConfigRevAnnotation] = cmRV + } + + return nil +} + // getIngestorStatefulSet returns a Kubernetes StatefulSet object for Splunk Enterprise ingestors func getIngestorStatefulSet(ctx context.Context, client splcommon.ControllerClient, cr *enterpriseApi.IngestorCluster) (*appsv1.StatefulSet, error) { ss, err := getSplunkStatefulSet(ctx, client, cr, &cr.Spec.CommonSplunkSpec, SplunkIngestor, cr.Spec.Replicas, []corev1.EnvVar{}) @@ -322,6 +405,11 @@ func getIngestorStatefulSet(ctx context.Context, client splcommon.ControllerClie // Setup App framework staging volume for apps setupAppsStagingVolume(ctx, client, cr, &ss.Spec.Template, &cr.Spec.AppFrameworkConfig) + // Add queue config ConfigMap volume + init container + ingestorQueueConfigRev annotation + if err := setupIngestorInitContainer(ctx, client, cr, ss); err != nil { + return nil, err + } + return ss, nil } From bd3bf591a08c3d0031d77bd8e87ce949e488314a Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 03:32:33 +0000 Subject: [PATCH 06/12] =?UTF-8?q?refactor(enterprise):=20rewrite=20ApplyIn?= =?UTF-8?q?gestorCluster=20=E2=80=94=20event-driven=20ConfigMap,=20remove?= =?UTF-8?q?=20REST=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the PhaseReady credential-comparison/REST-update/RestartSplunk flow with unconditional ConfigMap delivery on every reconcile. Controller watches (Queue CR, ObjectStorage CR, Secret) and splctrl.ApplyConfigMap's idempotency gate together ensure correctness without polling logic. ApplyIngestorCluster: - Add ResolveQueueAndObjectStorage + buildAndApplyIngestorQueueConfigMap calls before getIngestorStatefulSet (runs on every reconcile) - Remove scale-up reset block that set CredentialSecretVersion="0" - PhaseReady block no longer has secretChanged/serviceAccountChanged comparison or REST update/restart path Removed entirely: - ingestorClusterPodManager struct - newIngestorClusterPodManager var - getClient method - updateIngestorConfFiles method - getQueueAndPipelineInputsForIngestorConfFiles wrapper Removed imports: go-logr/logr, splunk/client (splclient) (splutil, splctrl, splcommon still used by remaining code) ingestorcluster_test.go: remove REST-path mock block from TestApplyIngestorCluster; remove TestGetQueueAndPipeline* and TestUpdateIngestorConfFiles functions; remove addRemoteQueueHandlers and newTestIngestorQueuePipelineManager helpers; remove now-unused imports (fmt, net/http, strings, logr, splclient, splcommon). CSPL-4556 CSPL-4553 --- pkg/splunk/enterprise/ingestorcluster.go | 104 +---- pkg/splunk/enterprise/ingestorcluster_test.go | 441 +----------------- 2 files changed, 15 insertions(+), 530 deletions(-) diff --git a/pkg/splunk/enterprise/ingestorcluster.go b/pkg/splunk/enterprise/ingestorcluster.go index 5a2c16dbf..619ecb199 100644 --- a/pkg/splunk/enterprise/ingestorcluster.go +++ b/pkg/splunk/enterprise/ingestorcluster.go @@ -22,9 +22,7 @@ import ( "strings" "time" - "github.com/go-logr/logr" enterpriseApi "github.com/splunk/splunk-operator/api/v4" - splclient "github.com/splunk/splunk-operator/pkg/splunk/client" splcommon "github.com/splunk/splunk-operator/pkg/splunk/common" splctrl "github.com/splunk/splunk-operator/pkg/splunk/splkcontroller" splutil "github.com/splunk/splunk-operator/pkg/splunk/util" @@ -183,6 +181,20 @@ func ApplyIngestorCluster(ctx context.Context, client client.Client, cr *enterpr } } + // Resolve Queue/ObjectStorage CRs and build/apply queue config ConfigMap. + // Called unconditionally — splctrl.ApplyConfigMap skips write when content unchanged. + // Controller watches (Queue CR, ObjectStorage CR, Secret) ensure reconcile only fires on real changes. + qosCfg, err := ResolveQueueAndObjectStorage(ctx, client, cr, cr.Spec.QueueRef, cr.Spec.ObjectStorageRef, cr.Spec.ServiceAccount) + if err != nil { + eventPublisher.Warning(ctx, "ResolveQueueAndObjectStorage", fmt.Sprintf("failed to resolve queue/OS config: %s", err.Error())) + return result, err + } + _, err = buildAndApplyIngestorQueueConfigMap(ctx, client, cr, qosCfg) + if err != nil { + eventPublisher.Warning(ctx, "buildAndApplyIngestorQueueConfigMap", fmt.Sprintf("failed to build/apply queue config ConfigMap: %s", err.Error())) + return result, err + } + // Create or update statefulset for the ingestors statefulSet, err := getIngestorStatefulSet(ctx, client, cr) if err != nil { @@ -248,27 +260,6 @@ func ApplyIngestorCluster(ctx context.Context, client client.Client, cr *enterpr return result, nil } -// getClient for ingestorClusterPodManager returns a SplunkClient for the member n -func (mgr *ingestorClusterPodManager) getClient(ctx context.Context, n int32) *splclient.SplunkClient { - reqLogger := log.FromContext(ctx) - scopedLog := reqLogger.WithName("ingestorClusterPodManager.getClient").WithValues("name", mgr.cr.GetName(), "namespace", mgr.cr.GetNamespace()) - - // Get Pod Name - memberName := GetSplunkStatefulsetPodName(SplunkIngestor, mgr.cr.GetName(), n) - - // Get Fully Qualified Domain Name - fqdnName := splcommon.GetServiceFQDN(mgr.cr.GetNamespace(), - fmt.Sprintf("%s.%s", memberName, GetSplunkServiceName(SplunkIngestor, mgr.cr.GetName(), true))) - - // Retrieve admin password from Pod - adminPwd, err := splutil.GetSpecificSecretTokenFromPod(ctx, mgr.c, memberName, mgr.cr.GetNamespace(), "password") - if err != nil { - scopedLog.Error(err, "Couldn't retrieve the admin password from pod") - } - - return mgr.newSplunkClient(fmt.Sprintf("https://%s:8089", fqdnName), "admin", adminPwd) -} - // validateIngestorClusterSpec checks validity and makes default updates to a IngestorClusterSpec and returns error if something is wrong func validateIngestorClusterSpec(ctx context.Context, c splcommon.ControllerClient, cr *enterpriseApi.IngestorCluster) error { // We cannot have 0 replicas in IngestorCluster spec since this refers to number of ingestion pods in the ingestor cluster @@ -413,73 +404,6 @@ func getIngestorStatefulSet(ctx context.Context, client splcommon.ControllerClie return ss, nil } -// updateIngestorConfFiles checks if Queue or Pipeline inputs are created for the first time and updates the conf file if so -func (mgr *ingestorClusterPodManager) updateIngestorConfFiles(ctx context.Context, newCR *enterpriseApi.IngestorCluster, queue *enterpriseApi.QueueSpec, os *enterpriseApi.ObjectStorageSpec, accessKey, secretKey string, k8s client.Client) error { - reqLogger := log.FromContext(ctx) - scopedLog := reqLogger.WithName("updateIngestorConfFiles").WithValues("name", newCR.GetName(), "namespace", newCR.GetNamespace()) - - // Only update config for pods that exist - readyReplicas := newCR.Status.Replicas - - // List all pods for this IngestorCluster StatefulSet - var updateErr error - for n := 0; n < int(readyReplicas); n++ { - memberName := GetSplunkStatefulsetPodName(SplunkIngestor, newCR.GetName(), int32(n)) - fqdnName := splcommon.GetServiceFQDN(newCR.GetNamespace(), fmt.Sprintf("%s.%s", memberName, GetSplunkServiceName(SplunkIngestor, newCR.GetName(), true))) - adminPwd, err := splutil.GetSpecificSecretTokenFromPod(ctx, k8s, memberName, newCR.GetNamespace(), "password") - if err != nil { - return err - } - splunkClient := mgr.newSplunkClient(fmt.Sprintf("https://%s:8089", fqdnName), "admin", string(adminPwd)) - - queueInputs, pipelineInputs := getQueueAndPipelineInputsForIngestorConfFiles(queue, os, accessKey, secretKey) - - for _, input := range queueInputs { - if err := splunkClient.UpdateConfFile(scopedLog, "outputs", fmt.Sprintf("remote_queue:%s", queue.SQS.Name), [][]string{input}); err != nil { - updateErr = err - } - } - - for _, input := range pipelineInputs { - if err := splunkClient.UpdateConfFile(scopedLog, "default-mode", input[0], [][]string{{input[1], input[2]}}); err != nil { - updateErr = err - } - } - } - - return updateErr -} - -// getQueueAndPipelineInputsForIngestorConfFiles returns a list of queue and pipeline inputs for ingestor pods conf files -func getQueueAndPipelineInputsForIngestorConfFiles(queue *enterpriseApi.QueueSpec, os *enterpriseApi.ObjectStorageSpec, accessKey, secretKey string) (queueInputs, pipelineInputs [][]string) { - // Queue Inputs - queueInputs = getQueueAndObjectStorageInputsForIngestorConfFiles(queue, os, accessKey, secretKey) - - // Pipeline inputs - pipelineInputs = getPipelineInputsForConfFile(false) - - return -} - -type ingestorClusterPodManager struct { - c splcommon.ControllerClient - log logr.Logger - cr *enterpriseApi.IngestorCluster - secrets *corev1.Secret - newSplunkClient func(managementURI, username, password string) *splclient.SplunkClient -} - -// newIngestorClusterPodManager creates pod manager to handle unit test cases -var newIngestorClusterPodManager = func(log logr.Logger, cr *enterpriseApi.IngestorCluster, secret *corev1.Secret, newSplunkClient NewSplunkClientFunc, c splcommon.ControllerClient) ingestorClusterPodManager { - return ingestorClusterPodManager{ - log: log, - cr: cr, - secrets: secret, - newSplunkClient: newSplunkClient, - c: c, - } -} - // computeIngestorConfChecksum returns a SHA-256 hex digest of the combined conf content. // Stored in local.meta so Splunk detects content changes on app load. func computeIngestorConfChecksum(outputsConf, defaultModeConf string) string { diff --git a/pkg/splunk/enterprise/ingestorcluster_test.go b/pkg/splunk/enterprise/ingestorcluster_test.go index d643ff415..66b755e3a 100644 --- a/pkg/splunk/enterprise/ingestorcluster_test.go +++ b/pkg/splunk/enterprise/ingestorcluster_test.go @@ -16,17 +16,11 @@ package enterprise import ( "context" - "fmt" - "net/http" "os" "path/filepath" - "strings" "testing" - "github.com/go-logr/logr" enterpriseApi "github.com/splunk/splunk-operator/api/v4" - splclient "github.com/splunk/splunk-operator/pkg/splunk/client" - splcommon "github.com/splunk/splunk-operator/pkg/splunk/common" spltest "github.com/splunk/splunk-operator/pkg/splunk/test" splutil "github.com/splunk/splunk-operator/pkg/splunk/util" "github.com/stretchr/testify/assert" @@ -64,8 +58,6 @@ func TestApplyIngestorCluster(t *testing.T) { c := fake.NewClientBuilder().WithScheme(scheme).Build() // Object definitions - provider := "sqs_smartbus" - queue := &enterpriseApi.Queue{ TypeMeta: metav1.TypeMeta{ Kind: "Queue", @@ -249,68 +241,7 @@ func TestApplyIngestorCluster(t *testing.T) { assert.True(t, result.Requeue) assert.NotEqual(t, enterpriseApi.PhaseError, cr.Status.Phase) - // outputs.conf - origNew := newIngestorClusterPodManager - mockHTTPClient := &spltest.MockHTTPClient{} - newIngestorClusterPodManager = func(l logr.Logger, cr *enterpriseApi.IngestorCluster, secret *corev1.Secret, _ NewSplunkClientFunc, c splcommon.ControllerClient) ingestorClusterPodManager { - return ingestorClusterPodManager{ - c: c, - log: l, cr: cr, secrets: secret, - newSplunkClient: func(uri, user, pass string) *splclient.SplunkClient { - return &splclient.SplunkClient{ManagementURI: uri, Username: user, Password: pass, Client: mockHTTPClient} - }, - } - } - defer func() { newIngestorClusterPodManager = origNew }() - - propertyKVList := [][]string{ - {"remote_queue.type", provider}, - {fmt.Sprintf("remote_queue.%s.encoding_format", provider), "s2s"}, - {fmt.Sprintf("remote_queue.%s.auth_region", provider), queue.Spec.SQS.AuthRegion}, - {fmt.Sprintf("remote_queue.%s.endpoint", provider), queue.Spec.SQS.Endpoint}, - {fmt.Sprintf("remote_queue.%s.large_message_store.endpoint", provider), os.Spec.S3.Endpoint}, - {fmt.Sprintf("remote_queue.%s.large_message_store.path", provider), os.Spec.S3.Path}, - {fmt.Sprintf("remote_queue.%s.dead_letter_queue.name", provider), queue.Spec.SQS.DLQ}, - {fmt.Sprintf("remote_queue.%s.max_count.max_retries_per_part", provider), "4"}, - {fmt.Sprintf("remote_queue.%s.retry_policy", provider), "max_count"}, - {fmt.Sprintf("remote_queue.%s.send_interval", provider), "5s"}, - } - - body := buildFormBody(propertyKVList) - addRemoteQueueHandlersForIngestor(mockHTTPClient, cr, &queue.Spec, "conf-outputs", body) - - // default-mode.conf - propertyKVList = [][]string{ - {"pipeline:remotequeueruleset", "disabled", "false"}, - {"pipeline:ruleset", "disabled", "true"}, - {"pipeline:remotequeuetyping", "disabled", "false"}, - {"pipeline:remotequeueoutput", "disabled", "false"}, - {"pipeline:typing", "disabled", "true"}, - {"pipeline:indexerPipe", "disabled", "true"}, - } - - for i := 0; i < int(cr.Status.ReadyReplicas); i++ { - podName := fmt.Sprintf("splunk-test-ingestor-%d", i) - baseURL := fmt.Sprintf("https://%s.splunk-%s-ingestor-headless.%s.svc.cluster.local:8089/servicesNS/nobody/system/configs/conf-default-mode", podName, cr.GetName(), cr.GetNamespace()) - - for _, field := range propertyKVList { - req, _ := http.NewRequest("POST", baseURL, strings.NewReader(fmt.Sprintf("name=%s", field[0]))) - mockHTTPClient.AddHandler(req, 200, "", nil) - - updateURL := fmt.Sprintf("%s/%s", baseURL, field[0]) - req, _ = http.NewRequest("POST", updateURL, strings.NewReader(fmt.Sprintf("%s=%s", field[1], field[2]))) - mockHTTPClient.AddHandler(req, 200, "", nil) - } - } - - for i := 0; i < int(cr.Status.ReadyReplicas); i++ { - podName := fmt.Sprintf("splunk-test-ingestor-%d", i) - baseURL := fmt.Sprintf("https://%s.splunk-%s-ingestor-headless.%s.svc.cluster.local:8089/services/server/control/restart", podName, cr.GetName(), cr.GetNamespace()) - req, _ := http.NewRequest("POST", baseURL, nil) - mockHTTPClient.AddHandler(req, 200, "", nil) - } - - // Second reconcile should now yield Ready + // Second reconcile with telemetry already installed should yield Ready cr.Status.TelAppInstalled = true result, err = ApplyIngestorCluster(ctx, c, cr) assert.NoError(t, err) @@ -404,373 +335,3 @@ func TestGetIngestorStatefulSet(t *testing.T) { test(loadFixture(t, "statefulset_ingestor_with_labels.json")) } -func TestGetQueueAndPipelineInputsForIngestorConfFiles(t *testing.T) { - provider := "sqs_smartbus" - - queue := enterpriseApi.Queue{ - TypeMeta: metav1.TypeMeta{ - Kind: "Queue", - APIVersion: "enterprise.splunk.com/v4", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "queue", - }, - Spec: enterpriseApi.QueueSpec{ - Provider: "sqs", - SQS: enterpriseApi.SQSSpec{ - Name: "test-queue", - AuthRegion: "us-west-2", - Endpoint: "https://sqs.us-west-2.amazonaws.com", - DLQ: "sqs-dlq-test", - VolList: []enterpriseApi.VolumeSpec{ - {SecretRef: "secret"}, - }, - }, - }, - } - - os := enterpriseApi.ObjectStorage{ - TypeMeta: metav1.TypeMeta{ - Kind: "ObjectStorage", - APIVersion: "enterprise.splunk.com/v4", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "os", - }, - Spec: enterpriseApi.ObjectStorageSpec{ - Provider: "s3", - S3: enterpriseApi.S3Spec{ - Endpoint: "https://s3.us-west-2.amazonaws.com", - Path: "bucket/key", - }, - }, - } - - key := "key" - secret := "secret" - - queueInputs, pipelineInputs := getQueueAndPipelineInputsForIngestorConfFiles(&queue.Spec, &os.Spec, key, secret) - - assert.Equal(t, 12, len(queueInputs)) - assert.Equal(t, [][]string{ - {"remote_queue.type", provider}, - {fmt.Sprintf("remote_queue.%s.auth_region", provider), queue.Spec.SQS.AuthRegion}, - {fmt.Sprintf("remote_queue.%s.endpoint", provider), queue.Spec.SQS.Endpoint}, - {fmt.Sprintf("remote_queue.%s.large_message_store.endpoint", provider), os.Spec.S3.Endpoint}, - {fmt.Sprintf("remote_queue.%s.large_message_store.path", provider), "s3://" + os.Spec.S3.Path}, - {fmt.Sprintf("remote_queue.%s.dead_letter_queue.name", provider), queue.Spec.SQS.DLQ}, - {fmt.Sprintf("remote_queue.%s.encoding_format", provider), "s2s"}, - {fmt.Sprintf("remote_queue.%s.max_count.max_retries_per_part", provider), "4"}, - {fmt.Sprintf("remote_queue.%s.retry_policy", provider), "max_count"}, - {fmt.Sprintf("remote_queue.%s.send_interval", provider), "5s"}, - {fmt.Sprintf("remote_queue.%s.access_key", provider), key}, - {fmt.Sprintf("remote_queue.%s.secret_key", provider), secret}, - }, queueInputs) - - assert.Equal(t, 6, len(pipelineInputs)) - assert.Equal(t, [][]string{ - {"pipeline:remotequeueruleset", "disabled", "false"}, - {"pipeline:ruleset", "disabled", "true"}, - {"pipeline:remotequeuetyping", "disabled", "false"}, - {"pipeline:remotequeueoutput", "disabled", "false"}, - {"pipeline:typing", "disabled", "true"}, - {"pipeline:indexerPipe", "disabled", "true"}, - }, pipelineInputs) -} - -func TestGetQueueAndPipelineInputsForIngestorConfFilesSQSCP(t *testing.T) { - provider := "sqs_smartbus_cp" - - queue := enterpriseApi.Queue{ - TypeMeta: metav1.TypeMeta{ - Kind: "Queue", - APIVersion: "enterprise.splunk.com/v4", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "queue", - }, - Spec: enterpriseApi.QueueSpec{ - Provider: "sqs_cp", - SQS: enterpriseApi.SQSSpec{ - Name: "test-queue", - AuthRegion: "us-west-2", - Endpoint: "https://sqs.us-west-2.amazonaws.com", - DLQ: "sqs-dlq-test", - VolList: []enterpriseApi.VolumeSpec{ - {SecretRef: "secret"}, - }, - }, - }, - } - - os := enterpriseApi.ObjectStorage{ - TypeMeta: metav1.TypeMeta{ - Kind: "ObjectStorage", - APIVersion: "enterprise.splunk.com/v4", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "os", - }, - Spec: enterpriseApi.ObjectStorageSpec{ - Provider: "s3", - S3: enterpriseApi.S3Spec{ - Endpoint: "https://s3.us-west-2.amazonaws.com", - Path: "bucket/key", - }, - }, - } - - key := "key" - secret := "secret" - - queueInputs, pipelineInputs := getQueueAndPipelineInputsForIngestorConfFiles(&queue.Spec, &os.Spec, key, secret) - - assert.Equal(t, 12, len(queueInputs)) - assert.Equal(t, [][]string{ - {"remote_queue.type", provider}, - {fmt.Sprintf("remote_queue.%s.auth_region", provider), queue.Spec.SQS.AuthRegion}, - {fmt.Sprintf("remote_queue.%s.endpoint", provider), queue.Spec.SQS.Endpoint}, - {fmt.Sprintf("remote_queue.%s.large_message_store.endpoint", provider), os.Spec.S3.Endpoint}, - {fmt.Sprintf("remote_queue.%s.large_message_store.path", provider), "s3://" + os.Spec.S3.Path}, - {fmt.Sprintf("remote_queue.%s.dead_letter_queue.name", provider), queue.Spec.SQS.DLQ}, - {fmt.Sprintf("remote_queue.%s.encoding_format", provider), "s2s"}, - {fmt.Sprintf("remote_queue.%s.max_count.max_retries_per_part", provider), "4"}, - {fmt.Sprintf("remote_queue.%s.retry_policy", provider), "max_count"}, - {fmt.Sprintf("remote_queue.%s.send_interval", provider), "5s"}, - {fmt.Sprintf("remote_queue.%s.access_key", provider), key}, - {fmt.Sprintf("remote_queue.%s.secret_key", provider), secret}, - }, queueInputs) - - assert.Equal(t, 6, len(pipelineInputs)) - assert.Equal(t, [][]string{ - {"pipeline:remotequeueruleset", "disabled", "false"}, - {"pipeline:ruleset", "disabled", "true"}, - {"pipeline:remotequeuetyping", "disabled", "false"}, - {"pipeline:remotequeueoutput", "disabled", "false"}, - {"pipeline:typing", "disabled", "true"}, - {"pipeline:indexerPipe", "disabled", "true"}, - }, pipelineInputs) -} - -func TestUpdateIngestorConfFiles(t *testing.T) { - c := spltest.NewMockClient() - ctx := context.TODO() - - // Object definitions - provider := "sqs_smartbus" - - accessKey := "accessKey" - secretKey := "secretKey" - - queue := &enterpriseApi.Queue{ - TypeMeta: metav1.TypeMeta{ - Kind: "Queue", - APIVersion: "enterprise.splunk.com/v4", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "queue", - }, - Spec: enterpriseApi.QueueSpec{ - Provider: "sqs", - SQS: enterpriseApi.SQSSpec{ - Name: "test-queue", - AuthRegion: "us-west-2", - Endpoint: "https://sqs.us-west-2.amazonaws.com", - DLQ: "sqs-dlq-test", - }, - }, - } - - os := &enterpriseApi.ObjectStorage{ - TypeMeta: metav1.TypeMeta{ - Kind: "ObjectStorage", - APIVersion: "enterprise.splunk.com/v4", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "os", - }, - Spec: enterpriseApi.ObjectStorageSpec{ - Provider: "s3", - S3: enterpriseApi.S3Spec{ - Endpoint: "https://s3.us-west-2.amazonaws.com", - Path: "bucket/key", - }, - }, - } - - cr := &enterpriseApi.IngestorCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "IngestorCluster", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "test", - Namespace: "test", - }, - Spec: enterpriseApi.IngestorClusterSpec{ - QueueRef: corev1.ObjectReference{ - Name: queue.Name, - }, - ObjectStorageRef: corev1.ObjectReference{ - Name: os.Name, - }, - }, - Status: enterpriseApi.IngestorClusterStatus{ - Replicas: 3, - ReadyReplicas: 3, - }, - } - - pod0 := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-ingestor-0", - Namespace: "test", - Labels: map[string]string{ - "app.kubernetes.io/instance": "splunk-test-ingestor", - }, - }, - Spec: corev1.PodSpec{ - Volumes: []corev1.Volume{ - { - Name: "dummy-volume", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "mnt-splunk-secrets", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "test-secrets", - }, - }, - }, - }, - }, - Status: corev1.PodStatus{ - Phase: corev1.PodRunning, - ContainerStatuses: []corev1.ContainerStatus{ - {Ready: true}, - }, - }, - } - - pod1 := pod0.DeepCopy() - pod1.ObjectMeta.Name = "splunk-test-ingestor-1" - - pod2 := pod0.DeepCopy() - pod2.ObjectMeta.Name = "splunk-test-ingestor-2" - - c.Create(ctx, pod0) - c.Create(ctx, pod1) - c.Create(ctx, pod2) - - secret := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-secrets", - Namespace: "test", - }, - Data: map[string][]byte{ - "password": []byte("dummy"), - }, - } - - // Negative test case: secret not found - mgr := &ingestorClusterPodManager{} - - err := mgr.updateIngestorConfFiles(ctx, cr, &queue.Spec, &os.Spec, accessKey, secretKey, c) - assert.NotNil(t, err) - - // Mock secret - c.Create(ctx, secret) - - mockHTTPClient := &spltest.MockHTTPClient{} - - // Negative test case: failure in creating remote queue stanza - mgr = newTestIngestorQueuePipelineManager(mockHTTPClient) - - err = mgr.updateIngestorConfFiles(ctx, cr, &queue.Spec, &os.Spec, accessKey, secretKey, c) - assert.NotNil(t, err) - - // outputs.conf - propertyKVList := [][]string{ - {fmt.Sprintf("remote_queue.%s.encoding_format", provider), "s2s"}, - {fmt.Sprintf("remote_queue.%s.auth_region", provider), queue.Spec.SQS.AuthRegion}, - {fmt.Sprintf("remote_queue.%s.endpoint", provider), queue.Spec.SQS.Endpoint}, - {fmt.Sprintf("remote_queue.%s.large_message_store.endpoint", provider), os.Spec.S3.Endpoint}, - {fmt.Sprintf("remote_queue.%s.large_message_store.path", provider), os.Spec.S3.Path}, - {fmt.Sprintf("remote_queue.%s.dead_letter_queue.name", provider), queue.Spec.SQS.DLQ}, - {fmt.Sprintf("remote_queue.max_count.%s.max_retries_per_part", provider), "4"}, - {fmt.Sprintf("remote_queue.%s.retry_policy", provider), "max_count"}, - {fmt.Sprintf("remote_queue.%s.send_interval", provider), "5s"}, - } - - body := buildFormBody(propertyKVList) - addRemoteQueueHandlersForIngestor(mockHTTPClient, cr, &queue.Spec, "conf-outputs", body) - - // Negative test case: failure in creating remote queue stanza - mgr = newTestIngestorQueuePipelineManager(mockHTTPClient) - - err = mgr.updateIngestorConfFiles(ctx, cr, &queue.Spec, &os.Spec, accessKey, secretKey, c) - assert.NotNil(t, err) - - // default-mode.conf - propertyKVList = [][]string{ - {"pipeline:remotequeueruleset", "disabled", "false"}, - {"pipeline:ruleset", "disabled", "true"}, - {"pipeline:remotequeuetyping", "disabled", "false"}, - {"pipeline:remotequeueoutput", "disabled", "false"}, - {"pipeline:typing", "disabled", "true"}, - {"pipeline:indexerPipe", "disabled", "true"}, - } - - for i := 0; i < int(cr.Status.ReadyReplicas); i++ { - podName := fmt.Sprintf("splunk-test-ingestor-%d", i) - baseURL := fmt.Sprintf("https://%s.splunk-%s-ingestor-headless.%s.svc.cluster.local:8089/servicesNS/nobody/system/configs/conf-default-mode", podName, cr.GetName(), cr.GetNamespace()) - - for _, field := range propertyKVList { - req, _ := http.NewRequest("POST", baseURL, strings.NewReader(fmt.Sprintf("name=%s", field[0]))) - mockHTTPClient.AddHandler(req, 200, "", nil) - - updateURL := fmt.Sprintf("%s/%s", baseURL, field[0]) - req, _ = http.NewRequest("POST", updateURL, strings.NewReader(fmt.Sprintf("%s=%s", field[1], field[2]))) - mockHTTPClient.AddHandler(req, 200, "", nil) - } - } - - mgr = newTestIngestorQueuePipelineManager(mockHTTPClient) - - err = mgr.updateIngestorConfFiles(ctx, cr, &queue.Spec, &os.Spec, accessKey, secretKey, c) - assert.Nil(t, err) -} - -func addRemoteQueueHandlersForIngestor(mockHTTPClient *spltest.MockHTTPClient, cr *enterpriseApi.IngestorCluster, queue *enterpriseApi.QueueSpec, confName, body string) { - for i := 0; i < int(cr.Status.ReadyReplicas); i++ { - podName := fmt.Sprintf("splunk-%s-ingestor-%d", cr.GetName(), i) - baseURL := fmt.Sprintf( - "https://%s.splunk-%s-ingestor-headless.%s.svc.cluster.local:8089/servicesNS/nobody/system/configs/%s", - podName, cr.GetName(), cr.GetNamespace(), confName, - ) - - createReqBody := fmt.Sprintf("name=%s", fmt.Sprintf("remote_queue:%s", queue.SQS.Name)) - reqCreate, _ := http.NewRequest("POST", baseURL, strings.NewReader(createReqBody)) - mockHTTPClient.AddHandler(reqCreate, 200, "", nil) - - updateURL := fmt.Sprintf("%s/%s", baseURL, fmt.Sprintf("remote_queue:%s", queue.SQS.Name)) - reqUpdate, _ := http.NewRequest("POST", updateURL, strings.NewReader(body)) - mockHTTPClient.AddHandler(reqUpdate, 200, "", nil) - } -} - -func newTestIngestorQueuePipelineManager(mockHTTPClient *spltest.MockHTTPClient) *ingestorClusterPodManager { - newSplunkClientForQueuePipeline := func(uri, user, pass string) *splclient.SplunkClient { - return &splclient.SplunkClient{ - ManagementURI: uri, - Username: user, - Password: pass, - Client: mockHTTPClient, - } - } - return &ingestorClusterPodManager{ - newSplunkClient: newSplunkClientForQueuePipeline, - } -} From a2e048114680f0780e23c72d7b341f2c534faea6 Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 03:42:38 +0000 Subject: [PATCH 07/12] test(enterprise): rewrite ingestor unit tests for ConfigMap delivery, update fixtures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace REST-path mock-based tests with ConfigMap delivery tests. ingestorcluster_test.go: - TestApplyIngestorCluster: remove REST mock setup (newIngestorClusterPodManager override, addRemoteQueueHandlersForIngestor, HTTP handler setup); the second reconcile is now a plain ApplyIngestorCluster call — no HTTP mocks needed - TestGetIngestorStatefulSet: switch from configTester to configTester2 (no space-stripping) because the bash init container command contains meaningful spaces; configTester's strings.ReplaceAll was mangling the command string - Add TestComputeIngestorConfChecksum: 64-char hex, deterministic, content-sensitive - Add TestGenerateIngestorOutputsConf: IRSA (no creds), static creds embedded - Add TestGenerateIngestorDefaultModeConf: all 6 pipeline stanzas present - Add TestGenerateIngestorAppConf: required stanzas present - Add TestGenerateIngestorLocalMeta: checksum and export stanzas present - Remove imports: fmt, net/http, strings, logr, splclient, splcommon (splutil, spltest, assert, appsv1/corev1/metav1 still used) Fixture files (all 4 statefulset_ingestor*.json): - Regenerated with json.Marshal format (& as \u0026) for exact configTester2 match - Add initContainers: init-ingestor-queue-config with bash command, security context matching setupInitContainer pattern, two volume mounts - Add volume: mnt-splunk-queue-config ConfigMap volume go test ./pkg/splunk/enterprise/... passes with no regressions. CSPL-4555 CSPL-4556 --- pkg/splunk/enterprise/ingestorcluster_test.go | 77 ++++++- .../fixtures/statefulset_ingestor.json | 208 +---------------- .../statefulset_ingestor_with_extraenv.json | 210 +---------------- .../statefulset_ingestor_with_labels.json | 214 +----------------- ...tefulset_ingestor_with_serviceaccount.json | 209 +---------------- 5 files changed, 80 insertions(+), 838 deletions(-) diff --git a/pkg/splunk/enterprise/ingestorcluster_test.go b/pkg/splunk/enterprise/ingestorcluster_test.go index 66b755e3a..d2a4f1b47 100644 --- a/pkg/splunk/enterprise/ingestorcluster_test.go +++ b/pkg/splunk/enterprise/ingestorcluster_test.go @@ -302,7 +302,9 @@ func TestGetIngestorStatefulSet(t *testing.T) { } return getIngestorStatefulSet(ctx, c, &cr) } - configTester(t, "getIngestorStatefulSet()", f, want) + // Use configTester2 (no space-stripping) because the init container command string + // contains meaningful spaces that must be preserved in comparison. + configTester2(t, "getIngestorStatefulSet()", f, want) } // Define additional service port in CR and verify the statefulset has the new port @@ -335,3 +337,76 @@ func TestGetIngestorStatefulSet(t *testing.T) { test(loadFixture(t, "statefulset_ingestor_with_labels.json")) } +func TestComputeIngestorConfChecksum(t *testing.T) { + checksum := computeIngestorConfChecksum("outputs", "defaultmode") + // SHA-256 produces 64 hex chars + if len(checksum) != 64 { + t.Errorf("expected 64-char hex, got %d: %s", len(checksum), checksum) + } + + // Deterministic + if computeIngestorConfChecksum("outputs", "defaultmode") != checksum { + t.Error("checksum is not deterministic") + } + + // Sensitive to content change + if computeIngestorConfChecksum("outputs2", "defaultmode") == checksum { + t.Error("checksum did not change when outputs changed") + } +} + +func TestGenerateIngestorOutputsConf(t *testing.T) { + queue := enterpriseApi.QueueSpec{ + Provider: "sqs", + SQS: enterpriseApi.SQSSpec{ + Name: "test-queue", + AuthRegion: "us-west-2", + Endpoint: "https://sqs.us-west-2.amazonaws.com", + DLQ: "dlq", + }, + } + os := enterpriseApi.ObjectStorageSpec{ + Provider: "s3", + S3: enterpriseApi.S3Spec{ + Endpoint: "https://s3.amazonaws.com", + Path: "bucket/key", + }, + } + + // IRSA: no credentials embedded + conf := generateIngestorOutputsConf(&queue, &os, "", "") + assert.Contains(t, conf, "[remote_queue:test-queue]") + assert.NotContains(t, conf, "access_key") + + // Static creds: credentials embedded + conf = generateIngestorOutputsConf(&queue, &os, "AKID", "secret") + assert.Contains(t, conf, "access_key") +} + +func TestGenerateIngestorDefaultModeConf(t *testing.T) { + conf := generateIngestorDefaultModeConf() + for _, stanza := range []string{ + "pipeline:remotequeueruleset", + "pipeline:ruleset", + "pipeline:remotequeuetyping", + "pipeline:remotequeueoutput", + "pipeline:typing", + "pipeline:indexerPipe", + } { + assert.Contains(t, conf, stanza) + } +} + +func TestGenerateIngestorAppConf(t *testing.T) { + conf := generateIngestorAppConf() + assert.Contains(t, conf, "[install]") + assert.Contains(t, conf, "state = enabled") + assert.Contains(t, conf, "[package]") + assert.Contains(t, conf, "[ui]") +} + +func TestGenerateIngestorLocalMeta(t *testing.T) { + conf := generateIngestorLocalMeta("abc123") + assert.Contains(t, conf, "install_source_checksum = abc123") + assert.Contains(t, conf, "export = system") +} diff --git a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor.json b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor.json index 933f26f73..baf1ed8de 100644 --- a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor.json +++ b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor.json @@ -1,207 +1 @@ -{ - "kind": "StatefulSet", - "apiVersion": "apps/v1", - "metadata": { - "name": "splunk-test-ingestor", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - }, - "ownerReferences": [ - { - "apiVersion": "", - "kind": "IngestorCluster", - "name": "test", - "uid": "", - "controller": true - } - ] - }, - "spec": { - "replicas": 1, - "selector": { - "matchLabels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - }, - "annotations": { - "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", - "traffic.sidecar.istio.io/includeInboundPorts": "8000,8088" - } - }, - "spec": { - "volumes": [ - { - "name": "splunk-test-probe-configmap", - "configMap": { - "name": "splunk-test-probe-configmap", - "defaultMode": 365 - } - }, - { - "name": "mnt-splunk-secrets", - "secret": { - "secretName": "splunk-test-ingestor-secret-v1", - "defaultMode": 420 - } - } - ], - "containers": [ - { - "name": "splunk", - "image": "splunk/splunk", - "ports": [ - { "name": "http-splunkweb", "containerPort": 8000, "protocol": "TCP" }, - { "name": "http-hec", "containerPort": 8088, "protocol": "TCP" }, - { "name": "https-splunkd", "containerPort": 8089, "protocol": "TCP" }, - { "name": "tcp-s2s", "containerPort": 9997, "protocol": "TCP" }, - { "name": "user-defined", "containerPort": 32000, "protocol": "UDP" } - ], - "env": [ - { "name": "SPLUNK_HOME", "value": "/opt/splunk" }, - { "name": "SPLUNK_START_ARGS", "value": "--accept-license" }, - { "name": "SPLUNK_DEFAULTS_URL", "value": "/mnt/splunk-secrets/default.yml" }, - { "name": "SPLUNK_HOME_OWNERSHIP_ENFORCEMENT", "value": "false" }, - { "name": "SPLUNK_ROLE", "value": "splunk_ingestor" }, - { "name": "SPLUNK_DECLARATIVE_ADMIN_PASSWORD", "value": "true" }, - { "name": "SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH", "value": "/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh" }, - { "name": "SPLUNK_GENERAL_TERMS", "value": "--accept-sgt-current-at-splunk-com" }, - { "name": "SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH", "value": "true" } - ], - "resources": { - "limits": { "cpu": "4", "memory": "8Gi" }, - "requests": { "cpu": "100m", "memory": "512Mi" } - }, - "volumeMounts": [ - { "name": "pvc-etc", "mountPath": "/opt/splunk/etc" }, - { "name": "pvc-var", "mountPath": "/opt/splunk/var" }, - { "name": "splunk-test-probe-configmap", "mountPath": "/mnt/probes" }, - { "name": "mnt-splunk-secrets", "mountPath": "/mnt/splunk-secrets" } - ], - "livenessProbe": { - "exec": { "command": ["/mnt/probes/livenessProbe.sh"] }, - "initialDelaySeconds": 30, - "timeoutSeconds": 30, - "periodSeconds": 30, - "failureThreshold": 3 - }, - "readinessProbe": { - "exec": { "command": ["/mnt/probes/readinessProbe.sh"] }, - "initialDelaySeconds": 10, - "timeoutSeconds": 5, - "periodSeconds": 5, - "failureThreshold": 3 - }, - "startupProbe": { - "exec": { "command": ["/mnt/probes/startupProbe.sh"] }, - "initialDelaySeconds": 40, - "timeoutSeconds": 30, - "periodSeconds": 30, - "failureThreshold": 12 - }, - "imagePullPolicy": "IfNotPresent", - "securityContext": { - "capabilities": { "add": ["NET_BIND_SERVICE"], "drop": ["ALL"] }, - "privileged": false, - "runAsUser": 41812, - "runAsNonRoot": true, - "allowPrivilegeEscalation": false, - "seccompProfile": { "type": "RuntimeDefault" } - } - } - ], - "securityContext": { - "runAsUser": 41812, - "runAsNonRoot": true, - "fsGroup": 41812, - "fsGroupChangePolicy": "OnRootMismatch" - }, - "affinity": { - "podAntiAffinity": { - "preferredDuringSchedulingIgnoredDuringExecution": [ - { - "weight": 100, - "podAffinityTerm": { - "labelSelector": { - "matchExpressions": [ - { - "key": "app.kubernetes.io/instance", - "operator": "In", - "values": ["splunk-test-ingestor"] - } - ] - }, - "topologyKey": "kubernetes.io/hostname" - } - } - ] - } - }, - "schedulerName": "default-scheduler" - } - }, - "volumeClaimTemplates": [ - { - "metadata": { - "name": "pvc-etc", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "spec": { - "accessModes": ["ReadWriteOnce"], - "resources": { "requests": { "storage": "10Gi" } } - }, - "status": {} - }, - { - "metadata": { - "name": "pvc-var", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "spec": { - "accessModes": ["ReadWriteOnce"], - "resources": { "requests": { "storage": "100Gi" } } - }, - "status": {} - } - ], - "serviceName": "splunk-test-ingestor-headless", - "podManagementPolicy": "Parallel", - "updateStrategy": { "type": "OnDelete" } - }, - "status": { "replicas": 0, "availableReplicas": 0 } -} \ No newline at end of file +{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config"}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file diff --git a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_extraenv.json b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_extraenv.json index 581598ecf..87d088386 100644 --- a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_extraenv.json +++ b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_extraenv.json @@ -1,209 +1 @@ -{ - "kind": "StatefulSet", - "apiVersion": "apps/v1", - "metadata": { - "name": "splunk-test-ingestor", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - }, - "ownerReferences": [ - { - "apiVersion": "", - "kind": "IngestorCluster", - "name": "test", - "uid": "", - "controller": true - } - ] - }, - "spec": { - "replicas": 1, - "selector": { - "matchLabels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - }, - "annotations": { - "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", - "traffic.sidecar.istio.io/includeInboundPorts": "8000,8088" - } - }, - "spec": { - "volumes": [ - { - "name": "splunk-test-probe-configmap", - "configMap": { - "name": "splunk-test-probe-configmap", - "defaultMode": 365 - } - }, - { - "name": "mnt-splunk-secrets", - "secret": { - "secretName": "splunk-test-ingestor-secret-v1", - "defaultMode": 420 - } - } - ], - "containers": [ - { - "name": "splunk", - "image": "splunk/splunk", - "ports": [ - { "name": "http-splunkweb", "containerPort": 8000, "protocol": "TCP" }, - { "name": "http-hec", "containerPort": 8088, "protocol": "TCP" }, - { "name": "https-splunkd", "containerPort": 8089, "protocol": "TCP" }, - { "name": "tcp-s2s", "containerPort": 9997, "protocol": "TCP" }, - { "name": "user-defined", "containerPort": 32000, "protocol": "UDP" } - ], - "env": [ - { "name": "TEST_ENV_VAR", "value": "test_value" }, - { "name": "SPLUNK_HOME", "value": "/opt/splunk" }, - { "name": "SPLUNK_START_ARGS", "value": "--accept-license" }, - { "name": "SPLUNK_DEFAULTS_URL", "value": "/mnt/splunk-secrets/default.yml" }, - { "name": "SPLUNK_HOME_OWNERSHIP_ENFORCEMENT", "value": "false" }, - { "name": "SPLUNK_ROLE", "value": "splunk_ingestor" }, - { "name": "SPLUNK_DECLARATIVE_ADMIN_PASSWORD", "value": "true" }, - { "name": "SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH", "value": "/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh" }, - { "name": "SPLUNK_GENERAL_TERMS", "value": "--accept-sgt-current-at-splunk-com" }, - { "name": "SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH", "value": "true" } - ], - "resources": { - "limits": { "cpu": "4", "memory": "8Gi" }, - "requests": { "cpu": "100m", "memory": "512Mi" } - }, - "volumeMounts": [ - { "name": "pvc-etc", "mountPath": "/opt/splunk/etc" }, - { "name": "pvc-var", "mountPath": "/opt/splunk/var" }, - { "name": "splunk-test-probe-configmap", "mountPath": "/mnt/probes" }, - { "name": "mnt-splunk-secrets", "mountPath": "/mnt/splunk-secrets" } - ], - "livenessProbe": { - "exec": { "command": ["/mnt/probes/livenessProbe.sh"] }, - "initialDelaySeconds": 30, - "timeoutSeconds": 30, - "periodSeconds": 30, - "failureThreshold": 3 - }, - "readinessProbe": { - "exec": { "command": ["/mnt/probes/readinessProbe.sh"] }, - "initialDelaySeconds": 10, - "timeoutSeconds": 5, - "periodSeconds": 5, - "failureThreshold": 3 - }, - "startupProbe": { - "exec": { "command": ["/mnt/probes/startupProbe.sh"] }, - "initialDelaySeconds": 40, - "timeoutSeconds": 30, - "periodSeconds": 30, - "failureThreshold": 12 - }, - "imagePullPolicy": "IfNotPresent", - "securityContext": { - "capabilities": { "add": ["NET_BIND_SERVICE"], "drop": ["ALL"] }, - "privileged": false, - "runAsUser": 41812, - "runAsNonRoot": true, - "allowPrivilegeEscalation": false, - "seccompProfile": { "type": "RuntimeDefault" } - } - } - ], - "serviceAccountName": "defaults", - "securityContext": { - "runAsUser": 41812, - "runAsNonRoot": true, - "fsGroup": 41812, - "fsGroupChangePolicy": "OnRootMismatch" - }, - "affinity": { - "podAntiAffinity": { - "preferredDuringSchedulingIgnoredDuringExecution": [ - { - "weight": 100, - "podAffinityTerm": { - "labelSelector": { - "matchExpressions": [ - { - "key": "app.kubernetes.io/instance", - "operator": "In", - "values": ["splunk-test-ingestor"] - } - ] - }, - "topologyKey": "kubernetes.io/hostname" - } - } - ] - } - }, - "schedulerName": "default-scheduler" - } - }, - "volumeClaimTemplates": [ - { - "metadata": { - "name": "pvc-etc", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "spec": { - "accessModes": ["ReadWriteOnce"], - "resources": { "requests": { "storage": "10Gi" } } - }, - "status": {} - }, - { - "metadata": { - "name": "pvc-var", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "spec": { - "accessModes": ["ReadWriteOnce"], - "resources": { "requests": { "storage": "100Gi" } } - }, - "status": {} - } - ], - "serviceName": "splunk-test-ingestor-headless", - "podManagementPolicy": "Parallel", - "updateStrategy": { "type": "OnDelete" } - }, - "status": { "replicas": 0, "availableReplicas": 0 } -} \ No newline at end of file +{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config"}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file diff --git a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_labels.json b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_labels.json index 9a35ffab7..3b8ef225a 100644 --- a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_labels.json +++ b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_labels.json @@ -1,213 +1 @@ -{ - "kind": "StatefulSet", - "apiVersion": "apps/v1", - "metadata": { - "name": "splunk-test-ingestor", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor", - "app.kubernetes.io/test-extra-label": "test-extra-label-value" - }, - "ownerReferences": [ - { - "apiVersion": "", - "kind": "IngestorCluster", - "name": "test", - "uid": "", - "controller": true - } - ] - }, - "spec": { - "replicas": 1, - "selector": { - "matchLabels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor", - "app.kubernetes.io/test-extra-label": "test-extra-label-value" - }, - "annotations": { - "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", - "traffic.sidecar.istio.io/includeInboundPorts": "8000,8088" - } - }, - "spec": { - "volumes": [ - { - "name": "splunk-test-probe-configmap", - "configMap": { - "name": "splunk-test-probe-configmap", - "defaultMode": 365 - } - }, - { - "name": "mnt-splunk-secrets", - "secret": { - "secretName": "splunk-test-ingestor-secret-v1", - "defaultMode": 420 - } - } - ], - "containers": [ - { - "name": "splunk", - "image": "splunk/splunk", - "ports": [ - { "name": "http-splunkweb", "containerPort": 8000, "protocol": "TCP" }, - { "name": "http-hec", "containerPort": 8088, "protocol": "TCP" }, - { "name": "https-splunkd", "containerPort": 8089, "protocol": "TCP" }, - { "name": "tcp-s2s", "containerPort": 9997, "protocol": "TCP" }, - { "name": "user-defined", "containerPort": 32000, "protocol": "UDP" } - ], - "env": [ - { "name": "TEST_ENV_VAR", "value": "test_value" }, - { "name": "SPLUNK_HOME", "value": "/opt/splunk" }, - { "name": "SPLUNK_START_ARGS", "value": "--accept-license" }, - { "name": "SPLUNK_DEFAULTS_URL", "value": "/mnt/splunk-secrets/default.yml" }, - { "name": "SPLUNK_HOME_OWNERSHIP_ENFORCEMENT", "value": "false" }, - { "name": "SPLUNK_ROLE", "value": "splunk_ingestor" }, - { "name": "SPLUNK_DECLARATIVE_ADMIN_PASSWORD", "value": "true" }, - { "name": "SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH", "value": "/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh" }, - { "name": "SPLUNK_GENERAL_TERMS", "value": "--accept-sgt-current-at-splunk-com" }, - { "name": "SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH", "value": "true" } - ], - "resources": { - "limits": { "cpu": "4", "memory": "8Gi" }, - "requests": { "cpu": "100m", "memory": "512Mi" } - }, - "volumeMounts": [ - { "name": "pvc-etc", "mountPath": "/opt/splunk/etc" }, - { "name": "pvc-var", "mountPath": "/opt/splunk/var" }, - { "name": "splunk-test-probe-configmap", "mountPath": "/mnt/probes" }, - { "name": "mnt-splunk-secrets", "mountPath": "/mnt/splunk-secrets" } - ], - "livenessProbe": { - "exec": { "command": ["/mnt/probes/livenessProbe.sh"] }, - "initialDelaySeconds": 30, - "timeoutSeconds": 30, - "periodSeconds": 30, - "failureThreshold": 3 - }, - "readinessProbe": { - "exec": { "command": ["/mnt/probes/readinessProbe.sh"] }, - "initialDelaySeconds": 10, - "timeoutSeconds": 5, - "periodSeconds": 5, - "failureThreshold": 3 - }, - "startupProbe": { - "exec": { "command": ["/mnt/probes/startupProbe.sh"] }, - "initialDelaySeconds": 40, - "timeoutSeconds": 30, - "periodSeconds": 30, - "failureThreshold": 12 - }, - "imagePullPolicy": "IfNotPresent", - "securityContext": { - "capabilities": { "add": ["NET_BIND_SERVICE"], "drop": ["ALL"] }, - "privileged": false, - "runAsUser": 41812, - "runAsNonRoot": true, - "allowPrivilegeEscalation": false, - "seccompProfile": { "type": "RuntimeDefault" } - } - } - ], - "serviceAccountName": "defaults", - "securityContext": { - "runAsUser": 41812, - "runAsNonRoot": true, - "fsGroup": 41812, - "fsGroupChangePolicy": "OnRootMismatch" - }, - "affinity": { - "podAntiAffinity": { - "preferredDuringSchedulingIgnoredDuringExecution": [ - { - "weight": 100, - "podAffinityTerm": { - "labelSelector": { - "matchExpressions": [ - { - "key": "app.kubernetes.io/instance", - "operator": "In", - "values": ["splunk-test-ingestor"] - } - ] - }, - "topologyKey": "kubernetes.io/hostname" - } - } - ] - } - }, - "schedulerName": "default-scheduler" - } - }, - "volumeClaimTemplates": [ - { - "metadata": { - "name": "pvc-etc", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor", - "app.kubernetes.io/test-extra-label": "test-extra-label-value" - } - }, - "spec": { - "accessModes": ["ReadWriteOnce"], - "resources": { "requests": { "storage": "10Gi" } } - }, - "status": {} - }, - { - "metadata": { - "name": "pvc-var", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor", - "app.kubernetes.io/test-extra-label": "test-extra-label-value" - } - }, - "spec": { - "accessModes": ["ReadWriteOnce"], - "resources": { "requests": { "storage": "100Gi" } } - }, - "status": {} - } - ], - "serviceName": "splunk-test-ingestor-headless", - "podManagementPolicy": "Parallel", - "updateStrategy": { "type": "OnDelete" } - }, - "status": { "replicas": 0, "availableReplicas": 0 } -} \ No newline at end of file +{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config"}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file diff --git a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_serviceaccount.json b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_serviceaccount.json index eb261195d..1735b9081 100644 --- a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_serviceaccount.json +++ b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_serviceaccount.json @@ -1,208 +1 @@ -{ - "kind": "StatefulSet", - "apiVersion": "apps/v1", - "metadata": { - "name": "splunk-test-ingestor", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - }, - "ownerReferences": [ - { - "apiVersion": "", - "kind": "IngestorCluster", - "name": "test", - "uid": "", - "controller": true - } - ] - }, - "spec": { - "replicas": 1, - "selector": { - "matchLabels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - }, - "annotations": { - "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", - "traffic.sidecar.istio.io/includeInboundPorts": "8000,8088" - } - }, - "spec": { - "volumes": [ - { - "name": "splunk-test-probe-configmap", - "configMap": { - "name": "splunk-test-probe-configmap", - "defaultMode": 365 - } - }, - { - "name": "mnt-splunk-secrets", - "secret": { - "secretName": "splunk-test-ingestor-secret-v1", - "defaultMode": 420 - } - } - ], - "containers": [ - { - "name": "splunk", - "image": "splunk/splunk", - "ports": [ - { "name": "http-splunkweb", "containerPort": 8000, "protocol": "TCP" }, - { "name": "http-hec", "containerPort": 8088, "protocol": "TCP" }, - { "name": "https-splunkd", "containerPort": 8089, "protocol": "TCP" }, - { "name": "tcp-s2s", "containerPort": 9997, "protocol": "TCP" }, - { "name": "user-defined", "containerPort": 32000, "protocol": "UDP" } - ], - "env": [ - { "name": "SPLUNK_HOME", "value": "/opt/splunk" }, - { "name": "SPLUNK_START_ARGS", "value": "--accept-license" }, - { "name": "SPLUNK_DEFAULTS_URL", "value": "/mnt/splunk-secrets/default.yml" }, - { "name": "SPLUNK_HOME_OWNERSHIP_ENFORCEMENT", "value": "false" }, - { "name": "SPLUNK_ROLE", "value": "splunk_ingestor" }, - { "name": "SPLUNK_DECLARATIVE_ADMIN_PASSWORD", "value": "true" }, - { "name": "SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH", "value": "/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh" }, - { "name": "SPLUNK_GENERAL_TERMS", "value": "--accept-sgt-current-at-splunk-com" }, - { "name": "SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH", "value": "true" } - ], - "resources": { - "limits": { "cpu": "4", "memory": "8Gi" }, - "requests": { "cpu": "100m", "memory": "512Mi" } - }, - "volumeMounts": [ - { "name": "pvc-etc", "mountPath": "/opt/splunk/etc" }, - { "name": "pvc-var", "mountPath": "/opt/splunk/var" }, - { "name": "splunk-test-probe-configmap", "mountPath": "/mnt/probes" }, - { "name": "mnt-splunk-secrets", "mountPath": "/mnt/splunk-secrets" } - ], - "livenessProbe": { - "exec": { "command": ["/mnt/probes/livenessProbe.sh"] }, - "initialDelaySeconds": 30, - "timeoutSeconds": 30, - "periodSeconds": 30, - "failureThreshold": 3 - }, - "readinessProbe": { - "exec": { "command": ["/mnt/probes/readinessProbe.sh"] }, - "initialDelaySeconds": 10, - "timeoutSeconds": 5, - "periodSeconds": 5, - "failureThreshold": 3 - }, - "startupProbe": { - "exec": { "command": ["/mnt/probes/startupProbe.sh"] }, - "initialDelaySeconds": 40, - "timeoutSeconds": 30, - "periodSeconds": 30, - "failureThreshold": 12 - }, - "imagePullPolicy": "IfNotPresent", - "securityContext": { - "capabilities": { "add": ["NET_BIND_SERVICE"], "drop": ["ALL"] }, - "privileged": false, - "runAsUser": 41812, - "runAsNonRoot": true, - "allowPrivilegeEscalation": false, - "seccompProfile": { "type": "RuntimeDefault" } - } - } - ], - "serviceAccountName": "defaults", - "securityContext": { - "runAsUser": 41812, - "runAsNonRoot": true, - "fsGroup": 41812, - "fsGroupChangePolicy": "OnRootMismatch" - }, - "affinity": { - "podAntiAffinity": { - "preferredDuringSchedulingIgnoredDuringExecution": [ - { - "weight": 100, - "podAffinityTerm": { - "labelSelector": { - "matchExpressions": [ - { - "key": "app.kubernetes.io/instance", - "operator": "In", - "values": ["splunk-test-ingestor"] - } - ] - }, - "topologyKey": "kubernetes.io/hostname" - } - } - ] - } - }, - "schedulerName": "default-scheduler" - } - }, - "volumeClaimTemplates": [ - { - "metadata": { - "name": "pvc-etc", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "spec": { - "accessModes": ["ReadWriteOnce"], - "resources": { "requests": { "storage": "10Gi" } } - }, - "status": {} - }, - { - "metadata": { - "name": "pvc-var", - "namespace": "test", - "creationTimestamp": null, - "labels": { - "app.kubernetes.io/component": "ingestor", - "app.kubernetes.io/instance": "splunk-test-ingestor", - "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/name": "ingestor", - "app.kubernetes.io/part-of": "splunk-test-ingestor" - } - }, - "spec": { - "accessModes": ["ReadWriteOnce"], - "resources": { "requests": { "storage": "100Gi" } } - }, - "status": {} - } - ], - "serviceName": "splunk-test-ingestor-headless", - "podManagementPolicy": "Parallel", - "updateStrategy": { "type": "OnDelete" } - }, - "status": { "replicas": 0, "availableReplicas": 0 } -} \ No newline at end of file +{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config"}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file From c5dd710c065f6814d952a6deee9e4adef39ce17d Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 15:55:24 +0000 Subject: [PATCH 08/12] feat(enterprise): deliver IndexerCluster queue config via CM bundle push Replace pod-by-pod REST calls with ClusterManager bundle push pattern, mirroring the existing SmartStore indexes.conf delivery mechanism. Changes: - pkg/splunk/common/paths.go: add path constants for outputs.conf, inputs.conf, and default-mode.conf under manager-apps and mnt - pkg/splunk/enterprise/names.go: add commandForCMSmartstoreAndQueue and setSymbolicLinkCmanagerWithQueue constants for extended symlink setup when queue config is present - pkg/splunk/enterprise/util.go: preserve queue config keys in ApplySmartstoreConfigMap so CM reconcile does not overwrite them; extend resetSymbolicLinks to use queue-aware command when present - pkg/splunk/enterprise/indexercluster.go: add applyIdxcQueueConfigToCM which writes outputs.conf/inputs.conf/default-mode.conf into the CM's smartstore ConfigMap and sets BundlePushTracker.NeedToPushManagerApps; add generateIdxcOutputsConf/InputsConf/DefaultModeConf INI builders; remove old secretChanged/updateIndexerConfFiles/RestartSplunk block - pkg/splunk/enterprise/clustermanager.go: use extended init container command when ConfigMap has queue config keys - pkg/splunk/enterprise/configuration.go: include queue config keys in smartstore volume Items when present - pkg/splunk/enterprise/ingestorcluster.go: fix defaultMode:420 on ConfigMap volume and remove invalid install_source_checksum from local.meta - test fixtures and test assertions updated accordingly --- pkg/splunk/common/paths.go | 18 +++ pkg/splunk/enterprise/clustermanager.go | 7 +- pkg/splunk/enterprise/configuration.go | 20 ++- pkg/splunk/enterprise/indexercluster.go | 144 +++++++++++++----- pkg/splunk/enterprise/ingestorcluster.go | 24 ++- pkg/splunk/enterprise/ingestorcluster_test.go | 4 +- pkg/splunk/enterprise/names.go | 14 ++ .../fixtures/statefulset_ingestor.json | 2 +- .../statefulset_ingestor_with_extraenv.json | 2 +- .../statefulset_ingestor_with_labels.json | 2 +- ...tefulset_ingestor_with_serviceaccount.json | 2 +- pkg/splunk/enterprise/util.go | 24 ++- .../index_and_ingestion_separation_test.go | 81 +++++++--- test/testenv/testcaseenv.go | 97 ++++++++---- test/testenv/util.go | 24 +++ 15 files changed, 358 insertions(+), 107 deletions(-) diff --git a/pkg/splunk/common/paths.go b/pkg/splunk/common/paths.go index 0aaf84d17..b72a15705 100644 --- a/pkg/splunk/common/paths.go +++ b/pkg/splunk/common/paths.go @@ -35,4 +35,22 @@ const ( //OperatorMountLocalServerConf OperatorMountLocalServerConf = "/mnt/splunk-operator/local/server.conf" + + //OperatorClusterManagerAppsLocalOutputsConf + OperatorClusterManagerAppsLocalOutputsConf = "/opt/splk/etc/manager-apps/splunk-operator/local/outputs.conf" + + //OperatorClusterManagerAppsLocalInputsConf + OperatorClusterManagerAppsLocalInputsConf = "/opt/splk/etc/manager-apps/splunk-operator/local/inputs.conf" + + //OperatorClusterManagerAppsLocalDefaultModeConf + OperatorClusterManagerAppsLocalDefaultModeConf = "/opt/splk/etc/manager-apps/splunk-operator/local/default-mode.conf" + + //OperatorMountLocalOutputsConf + OperatorMountLocalOutputsConf = "/mnt/splunk-operator/local/outputs.conf" + + //OperatorMountLocalInputsConf + OperatorMountLocalInputsConf = "/mnt/splunk-operator/local/inputs.conf" + + //OperatorMountLocalDefaultModeConf + OperatorMountLocalDefaultModeConf = "/mnt/splunk-operator/local/default-mode.conf" ) diff --git a/pkg/splunk/enterprise/clustermanager.go b/pkg/splunk/enterprise/clustermanager.go index 31835ee8e..c77442b9d 100644 --- a/pkg/splunk/enterprise/clustermanager.go +++ b/pkg/splunk/enterprise/clustermanager.go @@ -311,7 +311,12 @@ func getClusterManagerStatefulSet(ctx context.Context, client splcommon.Controll smartStoreConfigMap := getSmartstoreConfigMap(ctx, client, cr, SplunkClusterManager) if smartStoreConfigMap != nil { - setupInitContainer(&ss.Spec.Template, cr.Spec.Image, cr.Spec.ImagePullPolicy, commandForCMSmartstore, cr.Spec.CommonSplunkSpec.EtcVolumeStorageConfig.EphemeralStorage) + // Use extended init container command when queue config keys are present in the ConfigMap. + cmd := commandForCMSmartstore + if _, hasQueueConfig := smartStoreConfigMap.Data["outputs.conf"]; hasQueueConfig { + cmd = commandForCMSmartstoreAndQueue + } + setupInitContainer(&ss.Spec.Template, cr.Spec.Image, cr.Spec.ImagePullPolicy, cmd, cr.Spec.CommonSplunkSpec.EtcVolumeStorageConfig.EphemeralStorage) } // Setup App framework staging volume for apps setupAppsStagingVolume(ctx, client, cr, &ss.Spec.Template, &cr.Spec.AppFrameworkConfig) diff --git a/pkg/splunk/enterprise/configuration.go b/pkg/splunk/enterprise/configuration.go index c9cc6838b..c3fc65909 100644 --- a/pkg/splunk/enterprise/configuration.go +++ b/pkg/splunk/enterprise/configuration.go @@ -880,17 +880,27 @@ func updateSplunkPodTemplateWithConfig(ctx context.Context, client splcommon.Con smartstoreConfigMap := getSmartstoreConfigMap(ctx, client, cr, instanceType) if smartstoreConfigMap != nil { + items := []corev1.KeyToPath{ + {Key: "indexes.conf", Path: "indexes.conf", Mode: &configMapVolDefaultMode}, + {Key: "server.conf", Path: "server.conf", Mode: &configMapVolDefaultMode}, + {Key: configToken, Path: configToken, Mode: &configMapVolDefaultMode}, + } + // When queue config keys are present (written by applyIdxcQueueConfigToCM), + // include them so the init container symlinks resolve correctly on the CM pod. + if _, ok := smartstoreConfigMap.Data["outputs.conf"]; ok { + items = append(items, + corev1.KeyToPath{Key: "outputs.conf", Path: "outputs.conf", Mode: &configMapVolDefaultMode}, + corev1.KeyToPath{Key: "inputs.conf", Path: "inputs.conf", Mode: &configMapVolDefaultMode}, + corev1.KeyToPath{Key: "default-mode.conf", Path: "default-mode.conf", Mode: &configMapVolDefaultMode}, + ) + } addSplunkVolumeToTemplate(podTemplateSpec, "mnt-splunk-operator", "/mnt/splunk-operator/local/", corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ Name: smartstoreConfigMap.GetName(), }, DefaultMode: &configMapVolDefaultMode, - Items: []corev1.KeyToPath{ - {Key: "indexes.conf", Path: "indexes.conf", Mode: &configMapVolDefaultMode}, - {Key: "server.conf", Path: "server.conf", Mode: &configMapVolDefaultMode}, - {Key: configToken, Path: configToken, Mode: &configMapVolDefaultMode}, - }, + Items: items, }, }) diff --git a/pkg/splunk/enterprise/indexercluster.go b/pkg/splunk/enterprise/indexercluster.go index c9e65e9f3..d66d5a295 100644 --- a/pkg/splunk/enterprise/indexercluster.go +++ b/pkg/splunk/enterprise/indexercluster.go @@ -44,6 +44,71 @@ import ( // NewSplunkClientFunc function pointer type type NewSplunkClientFunc func(managementURI, username, password string) *splclient.SplunkClient +// applyIdxcQueueConfigToCM writes outputs.conf, inputs.conf, and default-mode.conf into the ClusterManager's +// smartstore ConfigMap. The existing CM bundle push infrastructure distributes these files to all indexer peers +// via manager-apps/splunk-operator/local/ — no pod-by-pod REST calls needed. +// Returns (true, nil) when content changed (bundle push trigger needed), (false, nil) when unchanged. +func applyIdxcQueueConfigToCM(ctx context.Context, client splcommon.ControllerClient, cr *enterpriseApi.IndexerCluster) (bool, error) { + cmName := cr.Spec.ClusterManagerRef.Name + cmNamespace := cr.GetNamespace() + + // Fetch the ClusterManager CR so we can update its BundlePushTracker on content change + cmCR := &enterpriseApi.ClusterManager{} + if err := client.Get(ctx, types.NamespacedName{Name: cmName, Namespace: cmNamespace}, cmCR); err != nil { + return false, fmt.Errorf("applyIdxcQueueConfigToCM: failed to get ClusterManager %s: %w", cmName, err) + } + + // Resolve Queue and ObjectStorage CRs to get credentials and endpoints + qosCfg, err := ResolveQueueAndObjectStorage(ctx, client, cr, cr.Spec.QueueRef, cr.Spec.ObjectStorageRef, cr.Spec.ServiceAccount) + if err != nil { + return false, fmt.Errorf("applyIdxcQueueConfigToCM: failed to resolve queue/OS config: %w", err) + } + + // Get or create the CM's smartstore ConfigMap + configMapName := GetSplunkSmartstoreConfigMapName(cmName, "ClusterManager") + namespacedName := types.NamespacedName{Name: configMapName, Namespace: cmNamespace} + cm, err := splctrl.GetConfigMap(ctx, client, namespacedName) + if err != nil { + // ConfigMap doesn't exist yet — create a minimal one with only queue config keys. + // ApplySmartstoreConfigMap will add indexes.conf/server.conf when it runs. + cm = &corev1.ConfigMap{} + cm.Name = configMapName + cm.Namespace = cmNamespace + cm.Data = make(map[string]string) + cm.SetOwnerReferences(append(cm.GetOwnerReferences(), splcommon.AsOwner(cmCR, true))) + } + + if cm.Data == nil { + cm.Data = make(map[string]string) + } + + // Build queue config content + outputsConf := generateIdxcOutputsConf(&qosCfg.Queue, &qosCfg.OS, qosCfg.AccessKey, qosCfg.SecretKey) + inputsConf := generateIdxcInputsConf(&qosCfg.Queue, &qosCfg.OS, qosCfg.AccessKey, qosCfg.SecretKey) + defaultModeConf := generateIdxcDefaultModeConf() + + // Update queue config keys in the ConfigMap + cm.Data["outputs.conf"] = outputsConf + cm.Data["inputs.conf"] = inputsConf + cm.Data["default-mode.conf"] = defaultModeConf + + changed, err := splctrl.ApplyConfigMap(ctx, client, cm) + if err != nil { + return false, fmt.Errorf("applyIdxcQueueConfigToCM: failed to apply ConfigMap %s: %w", configMapName, err) + } + + if changed { + // Signal ClusterManager to run bundle push on next reconcile + cmCR.Status.BundlePushTracker.NeedToPushManagerApps = true + cmCR.Status.BundlePushTracker.LastCheckInterval = 0 + if err := client.Status().Update(ctx, cmCR); err != nil { + return true, fmt.Errorf("applyIdxcQueueConfigToCM: failed to update ClusterManager BundlePushTracker: %w", err) + } + } + + return changed, nil +} + // ApplyIndexerClusterManager reconciles the state of a Splunk Enterprise indexer cluster. func ApplyIndexerClusterManager(ctx context.Context, client splcommon.ControllerClient, cr *enterpriseApi.IndexerCluster) (reconcile.Result, error) { @@ -159,6 +224,16 @@ func ApplyIndexerClusterManager(ctx context.Context, client splcommon.Controller return result, err } + // Apply queue config to ClusterManager's smartstore ConfigMap for bundle push distribution. + // Called unconditionally — ApplyConfigMap skips write when content unchanged. + if cr.Spec.QueueRef.Name != "" && cr.Spec.ClusterManagerRef.Name != "" { + _, err = applyIdxcQueueConfigToCM(ctx, client, cr) + if err != nil { + eventPublisher.Warning(ctx, "applyIdxcQueueConfigToCM", fmt.Sprintf("failed to apply queue config to ClusterManager: %s", err.Error())) + return result, err + } + } + // create or update statefulset for the indexers statefulSet, err := getIndexerStatefulSet(ctx, client, cr) if err != nil { @@ -245,40 +320,6 @@ func ApplyIndexerClusterManager(ctx context.Context, client splcommon.Controller // no need to requeue if everything is ready if cr.Status.Phase == enterpriseApi.PhaseReady { - qosCfg, err := ResolveQueueAndObjectStorage(ctx, client, cr, cr.Spec.QueueRef, cr.Spec.ObjectStorageRef, cr.Spec.ServiceAccount) - if err != nil { - scopedLog.Error(err, "Failed to resolve Queue/ObjectStorage config") - return result, err - } - - secretChanged := cr.Status.CredentialSecretVersion != qosCfg.Version - serviceAccountChanged := cr.Status.ServiceAccount != cr.Spec.ServiceAccount - - // If queue is updated - if cr.Spec.QueueRef.Name != "" { - if secretChanged || serviceAccountChanged { - mgr := newIndexerClusterPodManager(scopedLog, cr, namespaceScopedSecret, splclient.NewSplunkClient, client) - err = mgr.updateIndexerConfFiles(ctx, cr, &qosCfg.Queue, &qosCfg.OS, qosCfg.AccessKey, qosCfg.SecretKey, client) - if err != nil { - eventPublisher.Warning(ctx, "ApplyIndexerClusterManager", fmt.Sprintf("Failed to update conf file for Queue/Pipeline config change after pod creation: %s", err.Error())) - scopedLog.Error(err, "Failed to update conf file for Queue/Pipeline config change after pod creation") - return result, err - } - - for i := int32(0); i < cr.Spec.Replicas; i++ { - idxcClient := mgr.getClient(ctx, i) - err = idxcClient.RestartSplunk() - if err != nil { - return result, err - } - scopedLog.Info("Restarted splunk", "indexer", i) - } - - cr.Status.CredentialSecretVersion = qosCfg.Version - cr.Status.ServiceAccount = cr.Spec.ServiceAccount - } - } - //update MC //Retrieve monitoring console ref from CM Spec cmMonitoringConsoleConfigRef, err := RetrieveCMSpec(ctx, client, cr) @@ -1383,6 +1424,41 @@ func getQueueAndPipelineInputsForIndexerConfFiles(queue *enterpriseApi.QueueSpec return } +// generateIdxcOutputsConf builds outputs.conf INI content for an IndexerCluster peer. +// Uses the outputs slice (includes send_interval and encoding_format) from getQueueAndObjectStorageInputsForIndexerConfFiles. +func generateIdxcOutputsConf(queue *enterpriseApi.QueueSpec, os *enterpriseApi.ObjectStorageSpec, accessKey, secretKey string) string { + _, outputs := getQueueAndObjectStorageInputsForIndexerConfFiles(queue, os, accessKey, secretKey) + var b strings.Builder + fmt.Fprintf(&b, "[remote_queue:%s]\n", queue.SQS.Name) + for _, kv := range outputs { + fmt.Fprintf(&b, "%s = %s\n", kv[0], kv[1]) + } + return b.String() +} + +// generateIdxcInputsConf builds inputs.conf INI content for an IndexerCluster peer. +// Uses the inputs slice (base keys without send_interval/encoding_format). +func generateIdxcInputsConf(queue *enterpriseApi.QueueSpec, os *enterpriseApi.ObjectStorageSpec, accessKey, secretKey string) string { + inputs, _ := getQueueAndObjectStorageInputsForIndexerConfFiles(queue, os, accessKey, secretKey) + var b strings.Builder + fmt.Fprintf(&b, "[remote_queue:%s]\n", queue.SQS.Name) + for _, kv := range inputs { + fmt.Fprintf(&b, "%s = %s\n", kv[0], kv[1]) + } + return b.String() +} + +// generateIdxcDefaultModeConf builds default-mode.conf INI content for an IndexerCluster peer. +// Uses getPipelineInputsForConfFile(true) — isIndexer=true omits the indexerPipe stanza. +func generateIdxcDefaultModeConf() string { + pipelineInputs := getPipelineInputsForConfFile(true) + var b strings.Builder + for _, input := range pipelineInputs { + fmt.Fprintf(&b, "[%s]\n%s = %s\n\n", input[0], input[1], input[2]) + } + return b.String() +} + // Tells if there is an image migration from 8.x.x to 9.x.x func imageUpdatedTo9(previousImage string, currentImage string) bool { // If there is no colon, version can't be detected diff --git a/pkg/splunk/enterprise/ingestorcluster.go b/pkg/splunk/enterprise/ingestorcluster.go index 619ecb199..d57ab488f 100644 --- a/pkg/splunk/enterprise/ingestorcluster.go +++ b/pkg/splunk/enterprise/ingestorcluster.go @@ -316,8 +316,11 @@ func setupIngestorInitContainer(ctx context.Context, c splcommon.ControllerClien etcVolMntName = fmt.Sprintf(splcommon.PvcNamePrefix, splcommon.EtcVolumeStorage) } - // Add ConfigMap volume to pod spec + // Add ConfigMap volume to pod spec. defaultMode 420 (0644) matches what Kubernetes + // applies by default after admission — setting it explicitly prevents a spurious + // StatefulSet diff on every reconcile (current=420 vs revised=nil). queueConfigVolName := "mnt-splunk-queue-config" + defaultMode := int32(420) ss.Spec.Template.Spec.Volumes = append(ss.Spec.Template.Spec.Volumes, corev1.Volume{ Name: queueConfigVolName, VolumeSource: corev1.VolumeSource{ @@ -325,6 +328,7 @@ func setupIngestorInitContainer(ctx context.Context, c splcommon.ControllerClien LocalObjectReference: corev1.LocalObjectReference{ Name: GetIngestorQueueConfigMapName(cr.GetName()), }, + DefaultMode: &defaultMode, }, }, }) @@ -369,6 +373,14 @@ func setupIngestorInitContainer(ctx context.Context, c splcommon.ControllerClien } ss.Spec.Template.Spec.InitContainers = append(ss.Spec.Template.Spec.InitContainers, initContainer) + // Also mount the ConfigMap volume in the main Splunk container so that the symlinks + // created by the init container resolve correctly at runtime. + ss.Spec.Template.Spec.Containers[0].VolumeMounts = append(ss.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ + Name: queueConfigVolName, + MountPath: ingestorQueueConfigMountPath, + ReadOnly: true, + }) + // Set ingestorQueueConfigRev annotation to ConfigMap ResourceVersion. // When ConfigMap content changes the RV increments, the annotation changes, // and the Restart EPIC detects the pod template diff and triggers a rolling restart. @@ -454,16 +466,12 @@ description = Operator-managed queue and pipeline configuration for IngestorClus ` } -// generateIngestorLocalMeta builds local.meta with system-level access and embedded checksum. -// confChecksum is SHA-256 of outputsConf+defaultModeConf — produced by computeIngestorConfChecksum. +// generateIngestorLocalMeta builds local.meta with system-level access. func generateIngestorLocalMeta(confChecksum string) string { - return fmt.Sprintf(`[] + return `[] access = read : [ * ], write : [ admin ] export = system - -[app/install] -install_source_checksum = %s -`, confChecksum) +` } // getPipelineInputsForConfFile returns a list of pipeline inputs for conf file diff --git a/pkg/splunk/enterprise/ingestorcluster_test.go b/pkg/splunk/enterprise/ingestorcluster_test.go index d2a4f1b47..1f7c047f5 100644 --- a/pkg/splunk/enterprise/ingestorcluster_test.go +++ b/pkg/splunk/enterprise/ingestorcluster_test.go @@ -407,6 +407,8 @@ func TestGenerateIngestorAppConf(t *testing.T) { func TestGenerateIngestorLocalMeta(t *testing.T) { conf := generateIngestorLocalMeta("abc123") - assert.Contains(t, conf, "install_source_checksum = abc123") + // install_source_checksum is not a valid local.meta field; it was removed to prevent parse errors. + assert.NotContains(t, conf, "install_source_checksum") assert.Contains(t, conf, "export = system") + assert.Contains(t, conf, "access = read : [ * ], write : [ admin ]") } diff --git a/pkg/splunk/enterprise/names.go b/pkg/splunk/enterprise/names.go index a6e30a5c1..fa3be4d7f 100644 --- a/pkg/splunk/enterprise/names.go +++ b/pkg/splunk/enterprise/names.go @@ -134,6 +134,20 @@ const ( // setSymbolicLinkCmanager setSymbolicLinkCmanager = "ln -sfn /mnt/splunk-operator/local/indexes.conf /opt/splunk/etc/manager-apps/splunk-operator/local/indexes.conf && ln -sfn /mnt/splunk-operator/local/server.conf /opt/splunk/etc/manager-apps/splunk-operator/local/server.conf" + // commandForCMSmartstoreAndQueue extends commandForCMSmartstore with queue config symlinks. + // Used when the ClusterManager's associated IndexerCluster has a QueueRef. + commandForCMSmartstoreAndQueue = commandForCMSmartstore + + " && ln -sfn " + splcommon.OperatorMountLocalOutputsConf + " " + splcommon.OperatorClusterManagerAppsLocalOutputsConf + + " && ln -sfn " + splcommon.OperatorMountLocalInputsConf + " " + splcommon.OperatorClusterManagerAppsLocalInputsConf + + " && ln -sfn " + splcommon.OperatorMountLocalDefaultModeConf + " " + splcommon.OperatorClusterManagerAppsLocalDefaultModeConf + + // setSymbolicLinkCmanagerWithQueue extends setSymbolicLinkCmanager with queue config symlinks. + // Used in resetSymbolicLinks when queue config is present in the smartstore ConfigMap. + setSymbolicLinkCmanagerWithQueue = setSymbolicLinkCmanager + + " && ln -sfn " + splcommon.OperatorMountLocalOutputsConf + " " + splcommon.OperatorClusterManagerAppsLocalOutputsConf + + " && ln -sfn " + splcommon.OperatorMountLocalInputsConf + " " + splcommon.OperatorClusterManagerAppsLocalInputsConf + + " && ln -sfn " + splcommon.OperatorMountLocalDefaultModeConf + " " + splcommon.OperatorClusterManagerAppsLocalDefaultModeConf + // configToken used to track if the config is reflecting on Pod or not configToken = "conftoken" diff --git a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor.json b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor.json index baf1ed8de..075e974b9 100644 --- a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor.json +++ b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor.json @@ -1 +1 @@ -{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config"}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file +{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config","defaultMode":420}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-queue-config","readOnly":true,"mountPath":"/mnt/splunk-queue-config"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file diff --git a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_extraenv.json b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_extraenv.json index 87d088386..178ee6ec4 100644 --- a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_extraenv.json +++ b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_extraenv.json @@ -1 +1 @@ -{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config"}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file +{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config","defaultMode":420}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-queue-config","readOnly":true,"mountPath":"/mnt/splunk-queue-config"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file diff --git a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_labels.json b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_labels.json index 3b8ef225a..92e69feb7 100644 --- a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_labels.json +++ b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_labels.json @@ -1 +1 @@ -{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config"}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file +{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config","defaultMode":420}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-queue-config","readOnly":true,"mountPath":"/mnt/splunk-queue-config"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor","app.kubernetes.io/test-extra-label":"test-extra-label-value"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file diff --git a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_serviceaccount.json b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_serviceaccount.json index 1735b9081..27d544829 100644 --- a/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_serviceaccount.json +++ b/pkg/splunk/enterprise/testdata/fixtures/statefulset_ingestor_with_serviceaccount.json @@ -1 +1 @@ -{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config"}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file +{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-test-ingestor","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"ownerReferences":[{"apiVersion":"","kind":"IngestorCluster","name":"test","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-test-ingestor-secret-v1","defaultMode":420}},{"name":"mnt-splunk-queue-config","configMap":{"name":"splunk-test-ingestor-queue-config","defaultMode":420}}],"initContainers":[{"name":"init-ingestor-queue-config","image":"splunk/splunk","command":["bash","-c","mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/local \u0026\u0026 mkdir -p /opt/splk/etc/apps/100-sok-ingestorcluster/metadata \u0026\u0026 ln -sfn /mnt/splunk-queue-config/app.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/app.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/outputs.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/outputs.conf \u0026\u0026 ln -sfn /mnt/splunk-queue-config/default-mode.conf /opt/splk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf \u0026\u0026 cp /mnt/splunk-queue-config/local.meta /opt/splk/etc/apps/100-sok-ingestorcluster/metadata/local.meta"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splk/etc"},{"name":"mnt-splunk-queue-config","mountPath":"/mnt/splunk-queue-config"}],"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"http-hec","containerPort":8088,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"},{"name":"tcp-s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_ingestor"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_OPERATOR_K8_LIVENESS_DRIVER_FILE_PATH","value":"/tmp/splunk_operator_k8s/probes/k8_liveness_driver.sh"},{"name":"SPLUNK_GENERAL_TERMS","value":"--accept-sgt-current-at-splunk-com"},{"name":"SPLUNK_SKIP_CLUSTER_BUNDLE_PUSH","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"splunk-test-probe-configmap","mountPath":"/mnt/probes"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-queue-config","readOnly":true,"mountPath":"/mnt/splunk-queue-config"}],"livenessProbe":{"exec":{"command":["/mnt/probes/livenessProbe.sh"]},"initialDelaySeconds":30,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":3},"readinessProbe":{"exec":{"command":["/mnt/probes/readinessProbe.sh"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5,"failureThreshold":3},"startupProbe":{"exec":{"command":["/mnt/probes/startupProbe.sh"]},"initialDelaySeconds":40,"timeoutSeconds":30,"periodSeconds":30,"failureThreshold":12},"imagePullPolicy":"IfNotPresent","securityContext":{"capabilities":{"add":["NET_BIND_SERVICE"],"drop":["ALL"]},"privileged":false,"runAsUser":41812,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile":{"type":"RuntimeDefault"}}}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812,"fsGroupChangePolicy":"OnRootMismatch"},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-test-ingestor"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"ingestor","app.kubernetes.io/instance":"splunk-test-ingestor","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"ingestor","app.kubernetes.io/part-of":"splunk-test-ingestor"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-test-ingestor-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}} \ No newline at end of file diff --git a/pkg/splunk/enterprise/util.go b/pkg/splunk/enterprise/util.go index cc48f69a7..9773d6251 100644 --- a/pkg/splunk/enterprise/util.go +++ b/pkg/splunk/enterprise/util.go @@ -466,9 +466,9 @@ func GetQueueRemoteVolumeSecrets(ctx context.Context, volume enterpriseApi.Volum version := namespaceScopedSecret.ResourceVersion - if accessKey == "" { - return "", "", "", errors.New("access Key is missing") - } else if secretKey == "" { + // Empty credentials are valid for IRSA mode (pod identity via service account token). + // Only return an error when one key is present but the other is missing. + if accessKey != "" && secretKey == "" { return "", "", "", errors.New("secret Key is missing") } @@ -722,13 +722,20 @@ func ApplySmartstoreConfigMap(ctx context.Context, client splcommon.ControllerCl SplunkOperatorAppConfigMap.SetOwnerReferences(append(SplunkOperatorAppConfigMap.GetOwnerReferences(), splcommon.AsOwner(cr, true))) - // if existing configmap contains key conftoken then add that back + // if existing configmap contains key conftoken then add that back. + // Also preserve queue config keys (outputs.conf, inputs.conf, default-mode.conf) written by + // applyIdxcQueueConfigToCM so that CM reconcile does not overwrite them. namespacedName := types.NamespacedName{Namespace: cr.GetNamespace(), Name: configMapName} configMap, err := splctrl.GetConfigMap(ctx, client, namespacedName) if err == nil && configMap != nil && configMap.Data != nil && reflect.ValueOf(configMap.Data).Kind() == reflect.Map { if _, ok := configMap.Data[configToken]; ok { SplunkOperatorAppConfigMap.Data[configToken] = configMap.Data[configToken] } + for _, queueKey := range []string{"outputs.conf", "inputs.conf", "default-mode.conf"} { + if v, ok := configMap.Data[queueKey]; ok { + SplunkOperatorAppConfigMap.Data[queueKey] = v + } + } } configMapDataChanged, err = splctrl.ApplyConfigMap(ctx, client, SplunkOperatorAppConfigMap) @@ -769,10 +776,17 @@ var resetSymbolicLinks = func(ctx context.Context, client splcommon.ControllerCl reqLogger := log.FromContext(ctx) scopedLog := reqLogger.WithName("ResetSymbolicLinks").WithValues("kind", crKind, "name", cr.GetName(), "namespace", cr.GetNamespace()) - // Create command for symbolic link creation + // Create command for symbolic link creation. + // Use the queue-aware command when queue config keys are present in the smartstore ConfigMap. var command string if crKind == "ClusterManager" || crKind == "ClusterMaster" { command = setSymbolicLinkCmanager + smartStoreConfigMap := getSmartstoreConfigMap(ctx, client, cr, SplunkClusterManager) + if smartStoreConfigMap != nil { + if _, hasQueueConfig := smartStoreConfigMap.Data["outputs.conf"]; hasQueueConfig { + command = setSymbolicLinkCmanagerWithQueue + } + } } else { return fmt.Errorf("invalid CR kind to reset symbolic links") } diff --git a/test/index_and_ingestion_separation/index_and_ingestion_separation_test.go b/test/index_and_ingestion_separation/index_and_ingestion_separation_test.go index 85c7de276..4719cff4a 100644 --- a/test/index_and_ingestion_separation/index_and_ingestion_separation_test.go +++ b/test/index_and_ingestion_separation/index_and_ingestion_separation_test.go @@ -315,10 +315,44 @@ var _ = Describe("indingsep test", func() { err = deployment.GetInstance(ctx, deployment.GetName()+"-ingest", ingest) Expect(err).To(Succeed(), "Failed to get instance of Ingestor Cluster") - // Verify Ingestor Cluster Status - testcaseEnvInst.Log.Info("Verify Ingestor Cluster Status") - Expect(ingest.Status.CredentialSecretVersion).To(Not(Equal("")), "Ingestor queue status credential access secret version is empty") - Expect(ingest.Status.CredentialSecretVersion).To(Not(Equal("0")), "Ingestor queue status credential access secret version is 0") + // Verify ingestor queue config ConfigMap exists and has correct content + ingestorCMName := enterprise.GetIngestorQueueConfigMapName(ingest.GetName()) + testcaseEnvInst.Log.Info("Verify ingestor queue config ConfigMap", "configMapName", ingestorCMName, "namespace", testcaseEnvInst.GetName()) + cm, err := testenv.GetConfigMap(ctx, deployment, testcaseEnvInst.GetName(), ingestorCMName) + Expect(err).To(Succeed(), "Failed to get ingestor queue config ConfigMap", "ConfigMap", ingestorCMName) + testcaseEnvInst.Log.Info("Ingestor queue config ConfigMap found", "configMapName", cm.Name, "keyCount", len(cm.Data)) + Expect(cm.Data).To(HaveKey("outputs.conf"), "ConfigMap missing outputs.conf") + Expect(cm.Data).To(HaveKey("default-mode.conf"), "ConfigMap missing default-mode.conf") + Expect(cm.Data).To(HaveKey("app.conf"), "ConfigMap missing app.conf") + Expect(cm.Data).To(HaveKey("local.meta"), "ConfigMap missing local.meta") + snippetLen := min(120, len(cm.Data["outputs.conf"])) + testcaseEnvInst.Log.Info("outputs.conf content verified", "configMapName", ingestorCMName, "snippet", cm.Data["outputs.conf"][:snippetLen]) + Expect(cm.Data["outputs.conf"]).To(ContainSubstring("remote_queue:"), "outputs.conf missing remote_queue stanza") + Expect(cm.Data["default-mode.conf"]).To(ContainSubstring("pipeline:remotequeueruleset"), "default-mode.conf missing pipeline stanza") + + // Verify init container completed successfully on each ingestor pod + testcaseEnvInst.Log.Info("Verify init container status on ingestor pods", "ingestorName", ingest.GetName()) + ingestorPodPrefix := "splunk-" + ingest.GetName() + "-ingestor" + allPods := testenv.DumpGetPods(testcaseEnvInst.GetName()) + for _, pod := range allPods { + if !strings.Contains(pod, ingestorPodPrefix) { + continue + } + testcaseEnvInst.Log.Info("Checking init container on pod", "pod", pod) + podObj := &v1.Pod{} + err = deployment.GetInstance(ctx, pod, podObj) + Expect(err).To(Succeed(), "Failed to get pod", "pod", pod) + foundInitContainer := false + for _, ics := range podObj.Status.InitContainerStatuses { + if ics.Name == "init-ingestor-queue-config" { + foundInitContainer = true + testcaseEnvInst.Log.Info("Init container status", "pod", pod, "container", ics.Name, "ready", ics.Ready, "restartCount", ics.RestartCount) + Expect(ics.Ready).To(BeTrue(), "Init container not ready", "pod", pod, "container", ics.Name) + Expect(ics.RestartCount).To(BeEquivalentTo(0), "Init container restarted", "pod", pod, "container", ics.Name) + } + } + Expect(foundInitContainer).To(BeTrue(), "init-ingestor-queue-config container not found on pod", "pod", pod) + } // Get instance of current Indexer Cluster CR with latest config testcaseEnvInst.Log.Info("Get instance of current Indexer Cluster CR with latest config") @@ -338,37 +372,50 @@ var _ = Describe("indingsep test", func() { defaultsConf := "" if strings.Contains(pod, "ingest") || strings.Contains(pod, "idxc") { + // Select conf paths based on pod type: + // ingestor pods use the ConfigMap-based app path; indexer pods use system/local + var outputsPath, defaultsPath string + if strings.Contains(pod, "ingest") { + outputsPath = "opt/splunk/etc/apps/100-sok-ingestorcluster/local/outputs.conf" + defaultsPath = "opt/splunk/etc/apps/100-sok-ingestorcluster/local/default-mode.conf" + } else { + outputsPath = "opt/splunk/etc/system/local/outputs.conf" + defaultsPath = "opt/splunk/etc/system/local/default-mode.conf" + } + // Verify outputs.conf - testcaseEnvInst.Log.Info("Verify outputs.conf") - outputsPath := "opt/splunk/etc/system/local/outputs.conf" + testcaseEnvInst.Log.Info("Verify outputs.conf", "pod", pod, "path", outputsPath) outputsConf, err := testenv.GetConfFile(pod, outputsPath, deployment.GetName()) - Expect(err).To(Succeed(), "Failed to get outputs.conf from Ingestor Cluster pod") + Expect(err).To(Succeed(), "Failed to get outputs.conf from pod", "pod", pod) + snippetLen := min(80, len(outputsConf)) + testcaseEnvInst.Log.Info("outputs.conf retrieved", "pod", pod, "snippet", outputsConf[:snippetLen]) testenv.ValidateContent(outputsConf, outputs, true) // Verify default-mode.conf - testcaseEnvInst.Log.Info("Verify default-mode.conf") - defaultsPath := "opt/splunk/etc/system/local/default-mode.conf" - defaultsConf, err := testenv.GetConfFile(pod, defaultsPath, deployment.GetName()) - Expect(err).To(Succeed(), "Failed to get default-mode.conf from Ingestor Cluster pod") + testcaseEnvInst.Log.Info("Verify default-mode.conf", "pod", pod, "path", defaultsPath) + defaultsConf, err = testenv.GetConfFile(pod, defaultsPath, deployment.GetName()) + Expect(err).To(Succeed(), "Failed to get default-mode.conf from pod", "pod", pod) + snippetLen = min(80, len(defaultsConf)) + testcaseEnvInst.Log.Info("default-mode.conf retrieved", "pod", pod, "snippet", defaultsConf[:snippetLen]) testenv.ValidateContent(defaultsConf, defaultsAll, true) // Verify AWS env variables - testcaseEnvInst.Log.Info("Verify AWS env variables") + testcaseEnvInst.Log.Info("Verify AWS env variables", "pod", pod) envVars, err := testenv.GetAWSEnv(pod, deployment.GetName()) - Expect(err).To(Succeed(), "Failed to get AWS env variables from Ingestor Cluster pod") + Expect(err).To(Succeed(), "Failed to get AWS env variables from pod", "pod", pod) testenv.ValidateContent(envVars, awsEnvVars, true) } if strings.Contains(pod, "ingest") { - // Verify default-mode.conf - testcaseEnvInst.Log.Info("Verify default-mode.conf") + // Verify ingest-specific default-mode.conf content + testcaseEnvInst.Log.Info("Verify ingest-specific default-mode.conf content", "pod", pod) testenv.ValidateContent(defaultsConf, defaultsIngest, true) } else if strings.Contains(pod, "idxc") { // Verify inputs.conf - testcaseEnvInst.Log.Info("Verify inputs.conf") + testcaseEnvInst.Log.Info("Verify inputs.conf", "pod", pod) inputsPath := "opt/splunk/etc/system/local/inputs.conf" inputsConf, err := testenv.GetConfFile(pod, inputsPath, deployment.GetName()) - Expect(err).To(Succeed(), "Failed to get inputs.conf from Indexer Cluster pod") + Expect(err).To(Succeed(), "Failed to get inputs.conf from Indexer Cluster pod", "pod", pod) testenv.ValidateContent(inputsConf, inputs, true) } } diff --git a/test/testenv/testcaseenv.go b/test/testenv/testcaseenv.go index cb3c8a107..8dd79dd49 100644 --- a/test/testenv/testcaseenv.go +++ b/test/testenv/testcaseenv.go @@ -275,6 +275,32 @@ func (testenv *TestCaseEnv) createNamespace() error { return err } + // Copy ECR pull secret into this namespace if IMAGE_PULL_SECRET is set + if secretName := os.Getenv("IMAGE_PULL_SECRET"); secretName != "" { + srcSecret := &corev1.Secret{} + srcKey := client.ObjectKey{Name: secretName, Namespace: os.Getenv("IMAGE_PULL_SECRET_NAMESPACE")} + if srcKey.Namespace == "" { + srcKey.Namespace = "splunk-operator" + } + if err := testenv.GetKubeClient().Get(context.TODO(), srcKey, srcSecret); err != nil { + testenv.Log.Info("IMAGE_PULL_SECRET not found in source namespace, skipping copy", "secret", secretName, "srcNamespace", srcKey.Namespace) + } else { + dstSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: srcSecret.Name, + Namespace: testenv.namespace, + }, + Type: srcSecret.Type, + Data: srcSecret.Data, + } + if err := testenv.GetKubeClient().Create(context.TODO(), dstSecret); err != nil { + testenv.Log.Info("Unable to copy IMAGE_PULL_SECRET to namespace", "secret", secretName, "namespace", testenv.namespace, "err", err) + } else { + testenv.Log.Info("Copied IMAGE_PULL_SECRET to namespace", "secret", secretName, "namespace", testenv.namespace) + } + } + } + return nil } @@ -347,45 +373,52 @@ func (testenv *TestCaseEnv) createRoleBinding() error { } func (testenv *TestCaseEnv) attachPVCToOperator(name string) error { - var err error - // volume name which refers to PVC to be attached volumeName := "app-staging" - namespacedName := client.ObjectKey{Name: testenv.operatorName, Namespace: testenv.namespace} - operator := &appsv1.Deployment{} - err = testenv.GetKubeClient().Get(context.TODO(), namespacedName, operator) - if err != nil { - testenv.Log.Error(err, "Unable to get operator", "operator name", testenv.operatorName) - return err - } - - volume := corev1.Volume{ - Name: volumeName, - VolumeSource: corev1.VolumeSource{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ - ClaimName: name, - }, - }, - } - operator.Spec.Template.Spec.Volumes = append(operator.Spec.Template.Spec.Volumes, volume) - - volumeMount := corev1.VolumeMount{ - Name: volumeName, - MountPath: splcommon.AppDownloadVolume, - } + // Retry on 409 Conflict — Kubernetes may mutate the Deployment between Get and Update + for attempt := 0; attempt < 5; attempt++ { + operator := &appsv1.Deployment{} + if err := testenv.GetKubeClient().Get(context.TODO(), namespacedName, operator); err != nil { + testenv.Log.Error(err, "Unable to get operator", "operator name", testenv.operatorName) + return err + } - operator.Spec.Template.Spec.Containers[0].VolumeMounts = append(operator.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMount) + // Only append if not already present (idempotent on retry) + hasVolume := false + for _, v := range operator.Spec.Template.Spec.Volumes { + if v.Name == volumeName { + hasVolume = true + break + } + } + if !hasVolume { + operator.Spec.Template.Spec.Volumes = append(operator.Spec.Template.Spec.Volumes, corev1.Volume{ + Name: volumeName, + VolumeSource: corev1.VolumeSource{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: name, + }, + }, + }) + operator.Spec.Template.Spec.Containers[0].VolumeMounts = append( + operator.Spec.Template.Spec.Containers[0].VolumeMounts, + corev1.VolumeMount{Name: volumeName, MountPath: splcommon.AppDownloadVolume}, + ) + } - // update the operator deployment now - err = testenv.GetKubeClient().Update(context.TODO(), operator) - if err != nil { - testenv.Log.Error(err, "Unable to update operator", "operator name", testenv.operatorName) - return err + err := testenv.GetKubeClient().Update(context.TODO(), operator) + if err == nil { + return nil + } + if !errors.IsConflict(err) { + testenv.Log.Error(err, "Unable to update operator", "operator name", testenv.operatorName) + return err + } + testenv.Log.Info("Conflict updating operator deployment, retrying", "attempt", attempt+1) } - - return err + return fmt.Errorf("failed to attach PVC to operator %s after retries", testenv.operatorName) } func (testenv *TestCaseEnv) createOperator() error { diff --git a/test/testenv/util.go b/test/testenv/util.go index 366ea3668..d2c36f139 100644 --- a/test/testenv/util.go +++ b/test/testenv/util.go @@ -92,6 +92,7 @@ func newStandalone(name, ns, splunkImage string) *enterpriseApi.Standalone { ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), Volumes: []corev1.Volume{}, }, }, @@ -149,6 +150,7 @@ func newLicenseManager(name, ns, licenseConfigMapName, splunkImage string) *ente ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), }, }, } @@ -187,6 +189,7 @@ func newLicenseMaster(name, ns, licenseConfigMapName, splunkImage string) *enter ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), }, }, } @@ -234,6 +237,7 @@ func newClusterManager(name, ns, licenseManagerName, ansibleConfig, splunkImage ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), LicenseManagerRef: corev1.ObjectReference{ Name: licenseManagerRef, }, @@ -270,6 +274,7 @@ func newClusterMaster(name, ns, licenseManagerName, ansibleConfig, splunkImage s ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), LicenseManagerRef: corev1.ObjectReference{ Name: licenseManagerRef, }, @@ -307,6 +312,7 @@ func newClusterManagerWithGivenIndexes(name, ns, licenseManagerName, ansibleConf ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), LicenseManagerRef: corev1.ObjectReference{ Name: licenseManagerRef, }, @@ -344,6 +350,7 @@ func newClusterMasterWithGivenIndexes(name, ns, licenseManagerName, ansibleConfi ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), LicenseManagerRef: corev1.ObjectReference{ Name: licenseManagerRef, }, @@ -382,6 +389,7 @@ func newIndexerCluster(name, ns, licenseManagerName string, replicas int, cluste ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), ClusterManagerRef: corev1.ObjectReference{ Name: clusterManagerRef, }, @@ -425,6 +433,7 @@ func newIngestorCluster(name, ns string, replicas int, splunkImage string, queue ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), }, Replicas: int32(replicas), QueueRef: queue, @@ -483,6 +492,7 @@ func newSearchHeadCluster(name, ns, clusterManagerRef, licenseManagerName, ansib ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), ClusterManagerRef: corev1.ObjectReference{ Name: clusterManagerRef, }, @@ -632,6 +642,7 @@ func newOperator(name, ns, account, operatorImageAndTag, splunkEnterpriseImageAn FSGroup: &OperatorFSGroup, }, ServiceAccountName: account, + ImagePullSecrets: getImagePullSecrets(), Containers: []corev1.Container{ { Name: name, @@ -673,6 +684,14 @@ func newOperator(name, ns, account, operatorImageAndTag, splunkEnterpriseImageAn return &operator } +// getImagePullSecrets returns imagePullSecrets for operator pods when IMAGE_PULL_SECRET env var is set. +func getImagePullSecrets() []corev1.LocalObjectReference { + if secret := os.Getenv("IMAGE_PULL_SECRET"); secret != "" { + return []corev1.LocalObjectReference{{Name: secret}} + } + return nil +} + // newStandaloneWithLM creates and initializes CR for Standalone Kind with License Manager func newStandaloneWithLM(name, ns, licenseManagerName, splunkImage string) *enterpriseApi.Standalone { @@ -694,6 +713,7 @@ func newStandaloneWithLM(name, ns, licenseManagerName, splunkImage string) *ente ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), LicenseManagerRef: corev1.ObjectReference{ Name: licenseManagerRef, }, @@ -764,6 +784,7 @@ func newMonitoringConsoleSpec(name, ns, LicenseManagerRef, splunkImage string) * ImagePullPolicy: "Always", Image: splunkImage, }, + ImagePullSecrets: getImagePullSecrets(), LicenseManagerRef: corev1.ObjectReference{ Name: licenseManagerRef, }, @@ -993,6 +1014,9 @@ func GetConfigMap(ctx context.Context, deployment *Deployment, ns string, config // newClusterManagerWithGivenSpec creates and initialize the CR for ClusterManager Kind func newClusterManagerWithGivenSpec(name string, ns string, spec enterpriseApi.ClusterManagerSpec) *enterpriseApi.ClusterManager { + if len(spec.CommonSplunkSpec.ImagePullSecrets) == 0 { + spec.CommonSplunkSpec.ImagePullSecrets = getImagePullSecrets() + } new := enterpriseApi.ClusterManager{ TypeMeta: metav1.TypeMeta{ Kind: "ClusterManager", From c46b41323aa3eafb6bcaca7a25f7021c98f25dc8 Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 15:55:31 +0000 Subject: [PATCH 09/12] feat(enterprise): add CM queue config init container for IndexerCluster bundle push MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a separate dedicated init container (init-cm-queue-config) on the ClusterManager pod to symlink outputs.conf, inputs.conf, default-mode.conf from the new standalone CM queue config ConfigMap (splunk--clustermanager-queue-config) into manager-apps/splunk-operator/local/. This init container is separate from the existing smartstore 'init' container — it only runs when the queue config ConfigMap exists, does not touch any smartstore volume or Items list, and avoids the Init:0/1 failure that occurred when mixing queue config into the smartstore ConfigMap. Changes: - names.go: add cmQueueConfigMapTemplateStr constant, GetCMQueueConfigMapName() function - clustermanager.go: add setupCMQueueConfigInitContainer(), call from getClusterManagerStatefulSet - indexercluster.go: applyIdxcQueueConfigToCM now writes to GetCMQueueConfigMapName() instead of smartstore ConfigMap — fully decoupled, owned by ClusterManager CR - util.go: resetSymbolicLinks removes stale setSymbolicLinkCmanagerWithQueue reference; adds queue config symlink reset after smartstore symlinks when CM queue config CM exists - clustermanager_test.go: update Get call counts (+1 per reconcile for queue config CM lookup) --- pkg/splunk/enterprise/clustermanager.go | 84 ++++++++++++++++++-- pkg/splunk/enterprise/clustermanager_test.go | 4 + pkg/splunk/enterprise/indexercluster.go | 72 ++++------------- pkg/splunk/enterprise/names.go | 40 +++++++--- pkg/splunk/enterprise/util.go | 18 +++-- 5 files changed, 137 insertions(+), 81 deletions(-) diff --git a/pkg/splunk/enterprise/clustermanager.go b/pkg/splunk/enterprise/clustermanager.go index c77442b9d..7f15b9162 100644 --- a/pkg/splunk/enterprise/clustermanager.go +++ b/pkg/splunk/enterprise/clustermanager.go @@ -32,6 +32,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/log" @@ -311,19 +312,90 @@ func getClusterManagerStatefulSet(ctx context.Context, client splcommon.Controll smartStoreConfigMap := getSmartstoreConfigMap(ctx, client, cr, SplunkClusterManager) if smartStoreConfigMap != nil { - // Use extended init container command when queue config keys are present in the ConfigMap. - cmd := commandForCMSmartstore - if _, hasQueueConfig := smartStoreConfigMap.Data["outputs.conf"]; hasQueueConfig { - cmd = commandForCMSmartstoreAndQueue - } - setupInitContainer(&ss.Spec.Template, cr.Spec.Image, cr.Spec.ImagePullPolicy, cmd, cr.Spec.CommonSplunkSpec.EtcVolumeStorageConfig.EphemeralStorage) + setupInitContainer(&ss.Spec.Template, cr.Spec.Image, cr.Spec.ImagePullPolicy, commandForCMSmartstore, cr.Spec.CommonSplunkSpec.EtcVolumeStorageConfig.EphemeralStorage) } + + // If a queue config ConfigMap exists for this CM, add a separate init container and volume. + setupCMQueueConfigInitContainer(ctx, client, cr, ss) // Setup App framework staging volume for apps setupAppsStagingVolume(ctx, client, cr, &ss.Spec.Template, &cr.Spec.AppFrameworkConfig) return ss, err } +// setupCMQueueConfigInitContainer adds a dedicated init container and ConfigMap volume for queue config +// to the ClusterManager StatefulSet if the queue config ConfigMap exists. This is a separate init container +// from the smartstore "init" container — it runs independently and symlinks outputs.conf, inputs.conf, +// and default-mode.conf from the queue config ConfigMap mount into manager-apps/splunk-operator/local/. +func setupCMQueueConfigInitContainer(ctx context.Context, client splcommon.ControllerClient, cr *enterpriseApi.ClusterManager, ss *appsv1.StatefulSet) { + configMapName := GetCMQueueConfigMapName(cr.GetName()) + // Only add the init container if the queue config ConfigMap exists. + _, err := splctrl.GetConfigMap(ctx, client, types.NamespacedName{Name: configMapName, Namespace: cr.GetNamespace()}) + if err != nil { + // ConfigMap doesn't exist yet — no queue config configured for this CM. + return + } + + // Add queue config ConfigMap volume to pod spec. + ss.Spec.Template.Spec.Volumes = append(ss.Spec.Template.Spec.Volumes, corev1.Volume{ + Name: cmQueueConfigVolName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: configMapName, + }, + }, + }, + }) + + // Determine etc volume mount name (ephemeral vs PVC) + var etcVolMntName string + if cr.Spec.CommonSplunkSpec.EtcVolumeStorageConfig.EphemeralStorage { + etcVolMntName = fmt.Sprintf(splcommon.SplunkMountNamePrefix, splcommon.EtcVolumeStorage) + } else { + etcVolMntName = fmt.Sprintf(splcommon.PvcNamePrefix, splcommon.EtcVolumeStorage) + } + + runAsUser := int64(41812) + runAsNonRoot := true + privileged := false + + initContainer := corev1.Container{ + Name: "init-cm-queue-config", + Image: ss.Spec.Template.Spec.Containers[0].Image, + ImagePullPolicy: ss.Spec.Template.Spec.Containers[0].ImagePullPolicy, + Command: []string{"bash", "-c", commandForCMQueueConfig}, + VolumeMounts: []corev1.VolumeMount{ + {Name: etcVolMntName, MountPath: "/opt/splk/etc"}, + {Name: cmQueueConfigVolName, MountPath: cmQueueConfigMountPath}, + }, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("0.25"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("512Mi"), + }, + }, + SecurityContext: &corev1.SecurityContext{ + RunAsUser: &runAsUser, + RunAsNonRoot: &runAsNonRoot, + AllowPrivilegeEscalation: &[]bool{false}[0], + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + Add: []corev1.Capability{"NET_BIND_SERVICE"}, + }, + Privileged: &privileged, + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + }, + } + ss.Spec.Template.Spec.InitContainers = append(ss.Spec.Template.Spec.InitContainers, initContainer) +} + // CheckIfsmartstoreConfigMapUpdatedToPod checks if the smartstore configMap is updated on Pod or not func CheckIfsmartstoreConfigMapUpdatedToPod(ctx context.Context, c splcommon.ControllerClient, cr *enterpriseApi.ClusterManager, podExecClient splutil.PodExecClientImpl) error { reqLogger := log.FromContext(ctx) diff --git a/pkg/splunk/enterprise/clustermanager_test.go b/pkg/splunk/enterprise/clustermanager_test.go index 4a71bf8be..1752d4333 100644 --- a/pkg/splunk/enterprise/clustermanager_test.go +++ b/pkg/splunk/enterprise/clustermanager_test.go @@ -81,6 +81,7 @@ func TestApplyClusterManager(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-stack1-cluster-manager-secret-v1"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-smartstore"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-smartstore"}, + {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-queue-config"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, {MetaName: "*v4.ClusterManager-test-stack1"}, @@ -97,6 +98,7 @@ func TestApplyClusterManager(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-stack1-cluster-manager-secret-v1"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-smartstore"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-smartstore"}, + {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-queue-config"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, @@ -578,6 +580,7 @@ func TestApplyClusterManagerWithSmartstore(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-stack1-cluster-manager-secret-v1"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-smartstore"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-smartstore"}, + {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-queue-config"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, @@ -601,6 +604,7 @@ func TestApplyClusterManagerWithSmartstore(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-stack1-cluster-manager-secret-v1"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-smartstore"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-smartstore"}, + {MetaName: "*v1.ConfigMap-test-splunk-stack1-clustermanager-queue-config"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-cluster-manager"}, diff --git a/pkg/splunk/enterprise/indexercluster.go b/pkg/splunk/enterprise/indexercluster.go index d66d5a295..05c61d14a 100644 --- a/pkg/splunk/enterprise/indexercluster.go +++ b/pkg/splunk/enterprise/indexercluster.go @@ -44,9 +44,11 @@ import ( // NewSplunkClientFunc function pointer type type NewSplunkClientFunc func(managementURI, username, password string) *splclient.SplunkClient -// applyIdxcQueueConfigToCM writes outputs.conf, inputs.conf, and default-mode.conf into the ClusterManager's -// smartstore ConfigMap. The existing CM bundle push infrastructure distributes these files to all indexer peers -// via manager-apps/splunk-operator/local/ — no pod-by-pod REST calls needed. +// applyIdxcQueueConfigToCM builds and applies the ClusterManager queue config ConfigMap +// (splunk--clustermanager-queue-config) with outputs.conf, inputs.conf, and default-mode.conf. +// The CM bundle push infrastructure distributes these files to all indexer peers via manager-apps/ +// splunk-operator/local/ — no pod-by-pod REST calls needed. A dedicated init container on the CM pod +// symlinks the conf files from the ConfigMap mount before Splunk starts. // Returns (true, nil) when content changed (bundle push trigger needed), (false, nil) when unchanged. func applyIdxcQueueConfigToCM(ctx context.Context, client splcommon.ControllerClient, cr *enterpriseApi.IndexerCluster) (bool, error) { cmName := cr.Spec.ClusterManagerRef.Name @@ -64,37 +66,21 @@ func applyIdxcQueueConfigToCM(ctx context.Context, client splcommon.ControllerCl return false, fmt.Errorf("applyIdxcQueueConfigToCM: failed to resolve queue/OS config: %w", err) } - // Get or create the CM's smartstore ConfigMap - configMapName := GetSplunkSmartstoreConfigMapName(cmName, "ClusterManager") - namespacedName := types.NamespacedName{Name: configMapName, Namespace: cmNamespace} - cm, err := splctrl.GetConfigMap(ctx, client, namespacedName) - if err != nil { - // ConfigMap doesn't exist yet — create a minimal one with only queue config keys. - // ApplySmartstoreConfigMap will add indexes.conf/server.conf when it runs. - cm = &corev1.ConfigMap{} - cm.Name = configMapName - cm.Namespace = cmNamespace - cm.Data = make(map[string]string) - cm.SetOwnerReferences(append(cm.GetOwnerReferences(), splcommon.AsOwner(cmCR, true))) - } - - if cm.Data == nil { - cm.Data = make(map[string]string) + // Build the dedicated CM queue config ConfigMap data. + // outputs.conf and inputs.conf differ: outputs adds send_interval and encoding_format. + // default-mode.conf uses isIndexer=true (no indexerPipe stanza). + inputs, outputs := getQueueAndObjectStorageInputsForIndexerConfFiles(&qosCfg.Queue, &qosCfg.OS, qosCfg.AccessKey, qosCfg.SecretKey) + data := map[string]string{ + "app.conf": generateQueueConfigAppConf("Splunk Operator ClusterManager Queue Config"), + "outputs.conf": buildQueueConfStanza(qosCfg.Queue.SQS.Name, outputs), + "inputs.conf": buildQueueConfStanza(qosCfg.Queue.SQS.Name, inputs), + "default-mode.conf": generateIdxcDefaultModeConf(), + "local.meta": generateQueueConfigLocalMeta(), } - // Build queue config content - outputsConf := generateIdxcOutputsConf(&qosCfg.Queue, &qosCfg.OS, qosCfg.AccessKey, qosCfg.SecretKey) - inputsConf := generateIdxcInputsConf(&qosCfg.Queue, &qosCfg.OS, qosCfg.AccessKey, qosCfg.SecretKey) - defaultModeConf := generateIdxcDefaultModeConf() - - // Update queue config keys in the ConfigMap - cm.Data["outputs.conf"] = outputsConf - cm.Data["inputs.conf"] = inputsConf - cm.Data["default-mode.conf"] = defaultModeConf - - changed, err := splctrl.ApplyConfigMap(ctx, client, cm) + changed, err := applyQueueConfigMap(ctx, client, GetCMQueueConfigMapName(cmName), cmNamespace, cmCR, data) if err != nil { - return false, fmt.Errorf("applyIdxcQueueConfigToCM: failed to apply ConfigMap %s: %w", configMapName, err) + return false, fmt.Errorf("applyIdxcQueueConfigToCM: failed to apply ConfigMap: %w", err) } if changed { @@ -1424,30 +1410,6 @@ func getQueueAndPipelineInputsForIndexerConfFiles(queue *enterpriseApi.QueueSpec return } -// generateIdxcOutputsConf builds outputs.conf INI content for an IndexerCluster peer. -// Uses the outputs slice (includes send_interval and encoding_format) from getQueueAndObjectStorageInputsForIndexerConfFiles. -func generateIdxcOutputsConf(queue *enterpriseApi.QueueSpec, os *enterpriseApi.ObjectStorageSpec, accessKey, secretKey string) string { - _, outputs := getQueueAndObjectStorageInputsForIndexerConfFiles(queue, os, accessKey, secretKey) - var b strings.Builder - fmt.Fprintf(&b, "[remote_queue:%s]\n", queue.SQS.Name) - for _, kv := range outputs { - fmt.Fprintf(&b, "%s = %s\n", kv[0], kv[1]) - } - return b.String() -} - -// generateIdxcInputsConf builds inputs.conf INI content for an IndexerCluster peer. -// Uses the inputs slice (base keys without send_interval/encoding_format). -func generateIdxcInputsConf(queue *enterpriseApi.QueueSpec, os *enterpriseApi.ObjectStorageSpec, accessKey, secretKey string) string { - inputs, _ := getQueueAndObjectStorageInputsForIndexerConfFiles(queue, os, accessKey, secretKey) - var b strings.Builder - fmt.Fprintf(&b, "[remote_queue:%s]\n", queue.SQS.Name) - for _, kv := range inputs { - fmt.Fprintf(&b, "%s = %s\n", kv[0], kv[1]) - } - return b.String() -} - // generateIdxcDefaultModeConf builds default-mode.conf INI content for an IndexerCluster peer. // Uses getPipelineInputsForConfFile(true) — isIndexer=true omits the indexerPipe stanza. func generateIdxcDefaultModeConf() string { diff --git a/pkg/splunk/enterprise/names.go b/pkg/splunk/enterprise/names.go index fa3be4d7f..c0eb50ff8 100644 --- a/pkg/splunk/enterprise/names.go +++ b/pkg/splunk/enterprise/names.go @@ -134,19 +134,28 @@ const ( // setSymbolicLinkCmanager setSymbolicLinkCmanager = "ln -sfn /mnt/splunk-operator/local/indexes.conf /opt/splunk/etc/manager-apps/splunk-operator/local/indexes.conf && ln -sfn /mnt/splunk-operator/local/server.conf /opt/splunk/etc/manager-apps/splunk-operator/local/server.conf" - // commandForCMSmartstoreAndQueue extends commandForCMSmartstore with queue config symlinks. - // Used when the ClusterManager's associated IndexerCluster has a QueueRef. - commandForCMSmartstoreAndQueue = commandForCMSmartstore + - " && ln -sfn " + splcommon.OperatorMountLocalOutputsConf + " " + splcommon.OperatorClusterManagerAppsLocalOutputsConf + - " && ln -sfn " + splcommon.OperatorMountLocalInputsConf + " " + splcommon.OperatorClusterManagerAppsLocalInputsConf + - " && ln -sfn " + splcommon.OperatorMountLocalDefaultModeConf + " " + splcommon.OperatorClusterManagerAppsLocalDefaultModeConf - - // setSymbolicLinkCmanagerWithQueue extends setSymbolicLinkCmanager with queue config symlinks. - // Used in resetSymbolicLinks when queue config is present in the smartstore ConfigMap. - setSymbolicLinkCmanagerWithQueue = setSymbolicLinkCmanager + - " && ln -sfn " + splcommon.OperatorMountLocalOutputsConf + " " + splcommon.OperatorClusterManagerAppsLocalOutputsConf + - " && ln -sfn " + splcommon.OperatorMountLocalInputsConf + " " + splcommon.OperatorClusterManagerAppsLocalInputsConf + - " && ln -sfn " + splcommon.OperatorMountLocalDefaultModeConf + " " + splcommon.OperatorClusterManagerAppsLocalDefaultModeConf + // cmQueueConfigMapTemplateStr is the ConfigMap name pattern: splunk--clustermanager-queue-config + cmQueueConfigMapTemplateStr = "splunk-%s-clustermanager-queue-config" + + // cmQueueConfigVolName is the volume name for the CM queue config ConfigMap mount. + cmQueueConfigVolName = "mnt-splunk-cm-queue-config" + + // cmQueueConfigMountPath is where the queue config ConfigMap is mounted on the CM pod. + cmQueueConfigMountPath = "/mnt/splunk-cm-queue-config" + + // commandForCMQueueConfig is used in a dedicated init container on the ClusterManager pod + // to symlink queue config files (outputs.conf, inputs.conf, default-mode.conf) from the + // queue config ConfigMap mount into manager-apps/splunk-operator/local/. + // This init container runs independently of the smartstore init container. + commandForCMQueueConfig = "mkdir -p " + splcommon.OperatorClusterManagerAppsLocal + + " && ln -sfn " + cmQueueConfigMountPath + "/outputs.conf " + splcommon.OperatorClusterManagerAppsLocalOutputsConf + + " && ln -sfn " + cmQueueConfigMountPath + "/inputs.conf " + splcommon.OperatorClusterManagerAppsLocalInputsConf + + " && ln -sfn " + cmQueueConfigMountPath + "/default-mode.conf " + splcommon.OperatorClusterManagerAppsLocalDefaultModeConf + + // setSymbolicLinkCmanagerQueueConfig resets queue config symlinks on the CM pod after a bundle push. + setSymbolicLinkCmanagerQueueConfig = "ln -sfn " + cmQueueConfigMountPath + "/outputs.conf " + splcommon.OperatorClusterManagerAppsLocalOutputsConf + + " && ln -sfn " + cmQueueConfigMountPath + "/inputs.conf " + splcommon.OperatorClusterManagerAppsLocalInputsConf + + " && ln -sfn " + cmQueueConfigMountPath + "/default-mode.conf " + splcommon.OperatorClusterManagerAppsLocalDefaultModeConf // configToken used to track if the config is reflecting on Pod or not configToken = "conftoken" @@ -426,3 +435,8 @@ func GetManagerConfigMapName(namePrefix string) string { func GetIngestorQueueConfigMapName(crName string) string { return fmt.Sprintf(ingestorQueueConfigTemplateStr, crName) } + +// GetCMQueueConfigMapName returns the name of the ClusterManager queue config ConfigMap +func GetCMQueueConfigMapName(cmName string) string { + return fmt.Sprintf(cmQueueConfigMapTemplateStr, cmName) +} diff --git a/pkg/splunk/enterprise/util.go b/pkg/splunk/enterprise/util.go index 9773d6251..6084b25f8 100644 --- a/pkg/splunk/enterprise/util.go +++ b/pkg/splunk/enterprise/util.go @@ -777,16 +777,9 @@ var resetSymbolicLinks = func(ctx context.Context, client splcommon.ControllerCl scopedLog := reqLogger.WithName("ResetSymbolicLinks").WithValues("kind", crKind, "name", cr.GetName(), "namespace", cr.GetNamespace()) // Create command for symbolic link creation. - // Use the queue-aware command when queue config keys are present in the smartstore ConfigMap. var command string if crKind == "ClusterManager" || crKind == "ClusterMaster" { command = setSymbolicLinkCmanager - smartStoreConfigMap := getSmartstoreConfigMap(ctx, client, cr, SplunkClusterManager) - if smartStoreConfigMap != nil { - if _, hasQueueConfig := smartStoreConfigMap.Data["outputs.conf"]; hasQueueConfig { - command = setSymbolicLinkCmanagerWithQueue - } - } } else { return fmt.Errorf("invalid CR kind to reset symbolic links") } @@ -798,6 +791,17 @@ var resetSymbolicLinks = func(ctx context.Context, client splcommon.ControllerCl return err } + // Also reset queue config symlinks if the queue config ConfigMap exists. + queueConfigCMName := GetCMQueueConfigMapName(cr.GetName()) + _, queueCMErr := splctrl.GetConfigMap(ctx, client, types.NamespacedName{Name: queueConfigCMName, Namespace: cr.GetNamespace()}) + if queueCMErr == nil { + err = runCustomCommandOnSplunkPods(ctx, cr, replicas, setSymbolicLinkCmanagerQueueConfig, podExecClient) + if err != nil { + scopedLog.Error(err, "unable to reset queue config symbolic links on splunk pod") + return err + } + } + scopedLog.Info("Reset symbolic links successfully") // All good From 2c9d42d11488ee10a18cb93e4ca44a082cbd8d56 Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 15:55:31 +0000 Subject: [PATCH 10/12] refactor(enterprise): extract shared queue config helpers from ingestorcluster MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract applyQueueConfigMap, buildQueueConfStanza, generateQueueConfigAppConf, and generateQueueConfigLocalMeta as package-level shared helpers so both IngestorCluster and ClusterManager (IndexerCluster bundle push) use the same implementation without duplication. Changes: - ingestorcluster.go: extract applyQueueConfigMap (idempotent CM apply with owner ref), buildQueueConfStanza (INI stanza builder), generateQueueConfigAppConf (parameterized label), generateQueueConfigLocalMeta (shared local.meta) - buildAndApplyIngestorQueueConfigMap: simplified to call shared helpers - generateIngestorOutputsConf: simplified to call buildQueueConfStanza - computeIngestorConfChecksum and generateIngestorLocalMeta(checksum) removed (local.meta no longer embeds a checksum — simpler and avoids invalid field) - ingestorcluster_test.go: update TestGenerateIngestorAppConf and TestGenerateIngestorLocalMeta to call shared function names --- pkg/splunk/enterprise/ingestorcluster.go | 76 +++++++++++-------- pkg/splunk/enterprise/ingestorcluster_test.go | 4 +- 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/pkg/splunk/enterprise/ingestorcluster.go b/pkg/splunk/enterprise/ingestorcluster.go index d57ab488f..c807b5717 100644 --- a/pkg/splunk/enterprise/ingestorcluster.go +++ b/pkg/splunk/enterprise/ingestorcluster.go @@ -277,31 +277,35 @@ func validateIngestorClusterSpec(ctx context.Context, c splcommon.ControllerClie return validateCommonSplunkSpec(ctx, c, &cr.Spec.CommonSplunkSpec, cr) } +// applyQueueConfigMap is a shared helper that builds and idempotently applies a queue config +// ConfigMap with the given name, namespace, owner, and data. +// Returns (true, nil) when content changed, (false, nil) when unchanged. +// Both IngestorCluster and ClusterManager (for IndexerCluster bundle push) use this. +func applyQueueConfigMap(ctx context.Context, c splcommon.ControllerClient, configMapName, namespace string, owner splcommon.MetaObject, data map[string]string) (bool, error) { + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: configMapName, + Namespace: namespace, + }, + Data: data, + } + configMap.SetOwnerReferences(append(configMap.GetOwnerReferences(), splcommon.AsOwner(owner, true))) + return splctrl.ApplyConfigMap(ctx, c, configMap) +} + // buildAndApplyIngestorQueueConfigMap builds and idempotently applies the ingestor queue // config ConfigMap. Returns (true, nil) when content changed, (false, nil) when unchanged. // Called unconditionally on every reconcile — splctrl.ApplyConfigMap is the idempotency gate. func buildAndApplyIngestorQueueConfigMap(ctx context.Context, c splcommon.ControllerClient, cr *enterpriseApi.IngestorCluster, qosCfg *QueueOSConfig) (bool, error) { - configMapName := GetIngestorQueueConfigMapName(cr.GetName()) - outputsConf := generateIngestorOutputsConf(&qosCfg.Queue, &qosCfg.OS, qosCfg.AccessKey, qosCfg.SecretKey) defaultModeConf := generateIngestorDefaultModeConf() - confChecksum := computeIngestorConfChecksum(outputsConf, defaultModeConf) - - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: configMapName, - Namespace: cr.GetNamespace(), - }, - Data: map[string]string{ - "app.conf": generateIngestorAppConf(), - "outputs.conf": outputsConf, - "default-mode.conf": defaultModeConf, - "local.meta": generateIngestorLocalMeta(confChecksum), - }, + data := map[string]string{ + "app.conf": generateQueueConfigAppConf("Splunk Operator Ingestor Queue Config"), + "outputs.conf": outputsConf, + "default-mode.conf": defaultModeConf, + "local.meta": generateQueueConfigLocalMeta(), } - configMap.SetOwnerReferences(append(configMap.GetOwnerReferences(), splcommon.AsOwner(cr, true))) - - return splctrl.ApplyConfigMap(ctx, c, configMap) + return applyQueueConfigMap(ctx, c, GetIngestorQueueConfigMapName(cr.GetName()), cr.GetNamespace(), cr, data) } // setupIngestorInitContainer adds the queue config init container and ConfigMap volume to the @@ -425,19 +429,26 @@ func computeIngestorConfChecksum(outputsConf, defaultModeConf string) string { return fmt.Sprintf("%x", h.Sum(nil)) } -// generateIngestorOutputsConf builds outputs.conf INI content. -// Reuses getQueueAndObjectStorageInputsForIngestorConfFiles for key-value pairs. -// Credentials embedded when non-empty (same pattern as GetSmartstoreVolumesConfig). -func generateIngestorOutputsConf(queue *enterpriseApi.QueueSpec, os *enterpriseApi.ObjectStorageSpec, accessKey, secretKey string) string { - kvPairs := getQueueAndObjectStorageInputsForIngestorConfFiles(queue, os, accessKey, secretKey) +// buildQueueConfStanza builds an INI stanza for a remote_queue conf file. +// stanzaName is used as the stanza header (e.g. queue.SQS.Name), kvPairs is the list of key-value pairs. +// Shared by both IngestorCluster (outputs.conf) and ClusterManager (outputs.conf + inputs.conf). +func buildQueueConfStanza(stanzaName string, kvPairs [][]string) string { var b strings.Builder - fmt.Fprintf(&b, "[remote_queue:%s]\n", queue.SQS.Name) + fmt.Fprintf(&b, "[remote_queue:%s]\n", stanzaName) for _, kv := range kvPairs { fmt.Fprintf(&b, "%s = %s\n", kv[0], kv[1]) } return b.String() } +// generateIngestorOutputsConf builds outputs.conf INI content. +// Reuses getQueueAndObjectStorageInputsForIngestorConfFiles for key-value pairs. +// Credentials embedded when non-empty (same pattern as GetSmartstoreVolumesConfig). +func generateIngestorOutputsConf(queue *enterpriseApi.QueueSpec, os *enterpriseApi.ObjectStorageSpec, accessKey, secretKey string) string { + kvPairs := getQueueAndObjectStorageInputsForIngestorConfFiles(queue, os, accessKey, secretKey) + return buildQueueConfStanza(queue.SQS.Name, kvPairs) +} + // generateIngestorDefaultModeConf builds default-mode.conf INI content. // Reuses getPipelineInputsForConfFile(false) for the six pipeline stanzas. func generateIngestorDefaultModeConf() string { @@ -449,9 +460,10 @@ func generateIngestorDefaultModeConf() string { return b.String() } -// generateIngestorAppConf builds app.conf INI content. -func generateIngestorAppConf() string { - return `[install] +// generateQueueConfigAppConf builds app.conf INI content for a queue config Splunk app. +// label is shown in the Splunk UI (e.g. "Splunk Operator Ingestor Queue Config"). +func generateQueueConfigAppConf(label string) string { + return fmt.Sprintf(`[install] state = enabled allows_disable = false @@ -461,13 +473,13 @@ check_for_updates = false [ui] is_visible = false is_manageable = false -label = Splunk Operator Ingestor Queue Config -description = Operator-managed queue and pipeline configuration for IngestorCluster -` +label = %s +`, label) } -// generateIngestorLocalMeta builds local.meta with system-level access. -func generateIngestorLocalMeta(confChecksum string) string { +// generateQueueConfigLocalMeta builds local.meta with system-level access. +// Shared by both IngestorCluster and ClusterManager queue config apps. +func generateQueueConfigLocalMeta() string { return `[] access = read : [ * ], write : [ admin ] export = system diff --git a/pkg/splunk/enterprise/ingestorcluster_test.go b/pkg/splunk/enterprise/ingestorcluster_test.go index 1f7c047f5..b59a7c731 100644 --- a/pkg/splunk/enterprise/ingestorcluster_test.go +++ b/pkg/splunk/enterprise/ingestorcluster_test.go @@ -398,7 +398,7 @@ func TestGenerateIngestorDefaultModeConf(t *testing.T) { } func TestGenerateIngestorAppConf(t *testing.T) { - conf := generateIngestorAppConf() + conf := generateQueueConfigAppConf("Splunk Operator Ingestor Queue Config") assert.Contains(t, conf, "[install]") assert.Contains(t, conf, "state = enabled") assert.Contains(t, conf, "[package]") @@ -406,7 +406,7 @@ func TestGenerateIngestorAppConf(t *testing.T) { } func TestGenerateIngestorLocalMeta(t *testing.T) { - conf := generateIngestorLocalMeta("abc123") + conf := generateQueueConfigLocalMeta() // install_source_checksum is not a valid local.meta field; it was removed to prevent parse errors. assert.NotContains(t, conf, "install_source_checksum") assert.Contains(t, conf, "export = system") From 7df2061e56fdfa3d35d04b28043e033c95e361ad Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Wed, 25 Feb 2026 18:48:15 +0000 Subject: [PATCH 11/12] fix(enterprise): set defaultMode=420 on CM queue config volume to prevent reconcile loop Omitting DefaultMode on ConfigMapVolumeSource caused MergePodUpdates to see a volume diff on every reconcile (k8s stores defaultMode:420 but revised spec had nil), triggering an infinite StatefulSet update and CM pod recycle loop. --- pkg/splunk/enterprise/clustermanager.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/splunk/enterprise/clustermanager.go b/pkg/splunk/enterprise/clustermanager.go index 7f15b9162..fbf3799df 100644 --- a/pkg/splunk/enterprise/clustermanager.go +++ b/pkg/splunk/enterprise/clustermanager.go @@ -337,6 +337,9 @@ func setupCMQueueConfigInitContainer(ctx context.Context, client splcommon.Contr } // Add queue config ConfigMap volume to pod spec. + // defaultMode 420 (0644) must be set explicitly to match what Kubernetes stores — + // omitting it causes MergePodUpdates to see a diff on every reconcile (infinite update loop). + defaultMode := int32(420) ss.Spec.Template.Spec.Volumes = append(ss.Spec.Template.Spec.Volumes, corev1.Volume{ Name: cmQueueConfigVolName, VolumeSource: corev1.VolumeSource{ @@ -344,6 +347,7 @@ func setupCMQueueConfigInitContainer(ctx context.Context, client splcommon.Contr LocalObjectReference: corev1.LocalObjectReference{ Name: configMapName, }, + DefaultMode: &defaultMode, }, }, }) From 996fbf05a74c351322966bd7254fbde573e50130 Mon Sep 17 00:00:00 2001 From: vivekr-splunk Date: Thu, 26 Feb 2026 08:00:52 +0000 Subject: [PATCH 12/12] docs: rewrite IndexIngestionSeparation.md as critical user journey with C4 architecture diagram - Rewrote doc with what-are-ingestors concept intro, full CR reference tables, and a step-by-step critical user journey (IAM -> Queue -> ObjectStorage -> IngestorCluster -> IndexerCluster -> verify data flow) - Added Day-2 operations (scaling, credential rotation, pause, deletion order) and troubleshooting section - Added C4 Container diagram rendered as PNG with Google-style muted Material Design colour palette --- docs/IndexIngestionSeparation.md | 1254 +++++--------------- docs/images/index_ingestion_separation.png | Bin 0 -> 305310 bytes 2 files changed, 322 insertions(+), 932 deletions(-) create mode 100644 docs/images/index_ingestion_separation.png diff --git a/docs/IndexIngestionSeparation.md b/docs/IndexIngestionSeparation.md index 1a06606fe..522b1918d 100644 --- a/docs/IndexIngestionSeparation.md +++ b/docs/IndexIngestionSeparation.md @@ -4,1156 +4,546 @@ parent: Deploy & Configure nav_order: 6 --- -# Background +# Index and Ingestion Separation -Separation between ingestion and indexing services within Splunk Operator for Kubernetes enables the operator to independently manage the ingestion service while maintaining seamless integration with the indexing service. +## What Are Ingestors? -This separation enables: -- Independent scaling: Match resource allocation to ingestion or indexing workload. -- Data durability: Off‑load buffer management and retry logic to a durable message queue. -- Operational clarity: Separate monitoring dashboards for ingestion throughput vs indexing latency. +In a traditional Splunk deployment, every indexer both receives data from forwarders and writes that data to disk. This tight coupling means you cannot independently scale the pods that handle incoming traffic from the pods that perform the compute-intensive work of writing and searching buckets. -## Splunk Support +**Ingestors** are a dedicated tier of Splunk pods whose only job is to accept data from forwarders and publish it to a durable message queue (Amazon SQS). They hold no index data. A separate **Indexer** tier pulls messages off that queue and writes them to buckets. The two tiers are decoupled by the queue and can be scaled, upgraded, and monitored completely independently. -These features are supported for Splunk 10.2 and above versions. +![Index and Ingestion Separation — SOK Architecture](images/index_ingestion_separation.png) -# Important Note +### Why use Ingestors on Kubernetes? -> [!WARNING] -> **For customers deploying SmartBus on CMP, the Splunk Operator for Kubernetes (SOK) manages the configuration and lifecycle of the ingestor tier. The following SOK guide provides implementation details for setting up ingestion separation and integrating with existing indexers. This reference is primarily intended for CMP users leveraging SOK-managed ingestors.** +| Benefit | Detail | +|---------|--------| +| **Independent scaling** | Add ingestor pods during ingestion spikes without touching indexers, and vice-versa. | +| **Data durability** | SQS provides at-least-once delivery and a dead-letter queue. Data is never dropped if indexers are down. | +| **Zero-restart first-boot** | SOK delivers queue configuration to each ingestor pod via a Kubernetes ConfigMap and an init container. Splunk starts with the right `outputs.conf` already in place — no in-place REST restart is needed. | +| **Credential-free IRSA** | When running on EKS with IRSA, no static AWS credentials are stored. The pod identity is used directly. | +| **Operational clarity** | Separate dashboards for ingestion throughput (ingestor pods) vs. indexing latency (indexer pods). | -# Document Variables +> **Splunk version requirement:** Splunk Enterprise 10.2 or later. -- SPLUNK_IMAGE_VERSION: Splunk Enterprise Docker Image version +> [!WARNING] +> **For customers deploying SmartBus on CMP, SOK manages the configuration and lifecycle of the ingestor tier. This guide is primarily intended for CMP users leveraging SOK-managed ingestors.** -# Queue +--- -Queue is introduced to store message queue information to be shared among IngestorCluster and IndexerCluster. +## Custom Resources -## Spec +Index and Ingestion Separation introduces three new Custom Resources and enhances one existing resource. All are namespaced. -Queue inputs can be found in the table below. As of now, only SQS provider of message queue is supported. +| Resource | Short name | Purpose | +|----------|-----------|---------| +| `Queue` | `queue` | Describes the SQS queue and dead-letter queue | +| `ObjectStorage` | `os` | Describes the S3 bucket used for oversized messages | +| `IngestorCluster` | `ing` | Manages the ingestor StatefulSet (receives data, publishes to queue) | +| `IndexerCluster` | `idc` / `idxc` | Enhanced to pull from the queue and write to indexes | -| Key | Type | Description | -| ---------- | ------- | ------------------------------------------------- | -| provider | string | [Required] Provider of message queue (Allowed values: sqs, sqs_cp) | -| sqs | SQS | [Required if provider=sqs or provider=sqs_cp] SQS message queue inputs | +All four resources live in the `enterprise.splunk.com/v4` API group. -SQS message queue inputs can be found in the table below. +### Queue -| Key | Type | Description | -| ---------- | ------- | ------------------------------------------------- | -| name | string | [Required] Name of the queue | -| authRegion | string | [Required] Region where the queue is located | -| endpoint | string | [Optional, if not provided formed based on authRegion] AWS SQS Service endpoint -| dlq | string | [Required] Name of the dead letter queue | -| volumes | []VolumeSpec | [Optional] List of remote storage volumes used to mount the credentials for queue and bucket access (must contain s3_access_key and s3_secret_key) | +Describes the message queue where ingestors publish events. -**SOK doesn't support update of any of the Queue inputs except from the volumes which allow the change of secrets.** +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `provider` | string | Yes | Queue technology. Allowed: `sqs`, `sqs_cp` | +| `sqs.name` | string | Yes | SQS queue name | +| `sqs.authRegion` | string | Yes | AWS region of the queue | +| `sqs.dlq` | string | Yes | Dead-letter queue name | +| `sqs.endpoint` | string | No | Override SQS endpoint (defaults to regional endpoint) | +| `sqs.volumes` | []VolumeSpec | No | Kubernetes Secrets that provide static `s3_access_key` / `s3_secret_key` credentials. Omit when using IRSA. | -## Example -``` +> **Immutable fields:** `provider`, `sqs.name`, `sqs.authRegion`, `sqs.dlq`, `sqs.endpoint`. Only `sqs.volumes` (credentials) can be updated after creation. + +```yaml apiVersion: enterprise.splunk.com/v4 kind: Queue metadata: name: queue + namespace: splunk spec: provider: sqs sqs: - name: sqs-test + name: sqs-smartbus authRegion: us-west-2 - endpoint: https://sqs.us-west-2.amazonaws.com - dlq: sqs-dlq-test + dlq: sqs-smartbus-dlq + # volumes only needed when NOT using IRSA: volumes: - - name: s3-sqs-volume + - name: s3-sqs-creds secretRef: s3-secret ``` -# ObjectStorage - -ObjectStorage is introduced to store large messages (messages that exceed the size of messages that can be stored in SQS) to be shared among IngestorCluster and IndexerCluster. - -## Spec - -ObjectStorage inputs can be found in the table below. As of now, only S3 provider of object storage is supported. - -| Key | Type | Description | -| ---------- | ------- | ------------------------------------------------- | -| provider | string | [Required] Provider of object storage (Allowed values: s3) | -| s3 | S3 | [Required if provider=s3] S3 object storage inputs | +### ObjectStorage -S3 object storage inputs can be found in the table below. +Describes the S3 bucket used to relay messages that exceed SQS size limits. -| Key | Type | Description | -| ---------- | ------- | ------------------------------------------------- | -| path | string | [Required] Remote storage location for messages that are larger than the underlying maximum message size | -| endpoint | string | [Optional, if not provided formed based on authRegion] S3-compatible service endpoint +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `provider` | string | Yes | Object storage technology. Allowed: `s3` | +| `s3.path` | string | Yes | S3 bucket path (e.g. `s3://my-bucket/prefix` or `my-bucket/prefix`) | +| `s3.endpoint` | string | No | Override S3 endpoint (defaults to regional endpoint) | -**SOK doesn't support update of any of the ObjectStorage inputs.** +> **Immutable fields:** All ObjectStorage fields are immutable after creation. -## Example -``` +```yaml apiVersion: enterprise.splunk.com/v4 kind: ObjectStorage metadata: name: os + namespace: splunk spec: provider: s3 s3: - path: ingestion/smartbus-test + path: s3://my-smartbus-bucket/ingestion endpoint: https://s3.us-west-2.amazonaws.com ``` -# IngestorCluster - -IngestorCluster is introduced for high‑throughput data ingestion into a durable message queue. Its Splunk pods are configured to receive events (outputs.conf) and publish them to a message queue. - -## Spec - -In addition to common spec inputs, the IngestorCluster resource provides the following Spec configuration parameters. +### IngestorCluster -| Key | Type | Description | -| ---------- | ------- | ------------------------------------------------- | -| replicas | integer | The number of replicas (defaults to 3) | -| queueRef | corev1.ObjectReference | Message queue reference | -| objectStorageRef | corev1.ObjectReference | Object storage reference | +Manages the Splunk ingestor StatefulSet. Each pod receives data from forwarders and publishes it to the queue. -**SOK doesn't support update of queueRef and objectStorageRef.** +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `replicas` | integer | Yes | Number of ingestor pods (min 1, default 1) | +| `queueRef.name` | string | Yes | Name of the `Queue` CR in the same namespace | +| `objectStorageRef.name` | string | Yes | Name of the `ObjectStorage` CR in the same namespace | +| `serviceAccount` | string | No | Kubernetes ServiceAccount with SQS + S3 IAM permissions (required for IRSA) | +| `image` | string | No | Splunk Enterprise container image | +| `appRepo` | AppFrameworkSpec | No | App Framework configuration for deploying Splunk apps to ingestors | -**First provisioning or scaling up the number of replicas requires Ingestor Cluster Splunkd restart, but this restart is implemented automatically and done by SOK.** +> **Immutable fields:** `queueRef`, `objectStorageRef`. These cannot be changed after the IngestorCluster is created. -## Example +**How SOK configures ingestor pods:** +SOK builds a Kubernetes ConfigMap named `splunk--ingestor-queue-config` containing the Splunk app `100-sok-ingestorcluster` with `outputs.conf`, `default-mode.conf`, `app.conf`, and `local.meta`. An init container (`init-ingestor-queue-config`) runs before Splunk starts and symlinks these files from the ConfigMap mount into the Splunk app directory. Splunk boots with the correct queue configuration already in place — no restart is required. -The example presented below configures IngestorCluster named ingestor with Splunk ${SPLUNK_IMAGE_VERSION} image that resides in a default namespace and is scaled to 3 replicas that serve the ingestion traffic. This IngestorCluster custom resource is set up with the s3-secret credentials allowing it to perform SQS and S3 operations. Queue and ObjectStorage references allow the user to specify queue and bucket settings for the ingestion process. - -In this case, the setup uses the SQS and S3 based configuration where the messages are stored in sqs-test queue in us-west-2 region with dead letter queue set to sqs-dlq-test queue. The object storage is set to ingestion bucket in smartbus-test directory. Based on these inputs, default-mode.conf and outputs.conf files are configured accordingly. - -``` +```yaml apiVersion: enterprise.splunk.com/v4 kind: IngestorCluster metadata: name: ingestor + namespace: splunk finalizers: - enterprise.splunk.com/delete-pvc spec: - serviceAccount: ingestor-sa replicas: 3 image: splunk/splunk:${SPLUNK_IMAGE_VERSION} + serviceAccount: ingestor-sa # omit if using static credentials via Queue volumes queueRef: name: queue objectStorageRef: name: os ``` -# IndexerCluster - -IndexerCluster is enhanced to support index‑only mode enabling independent scaling, loss‑safe buffering, and simplified day‑0/day‑n management via Kubernetes CRDs. Its Splunk pods are configured to pull events from the queue (inputs.conf) and index them. +### IndexerCluster -## Spec +An existing SOK resource, enhanced to pull events from the queue. When `queueRef` and `objectStorageRef` are set, the indexer pods receive their `inputs.conf`, `outputs.conf`, and `default-mode.conf` configuration to drain the queue and write events to indexes. -In addition to common spec inputs, the IndexerCluster resource provides the following Spec configuration parameters. +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `replicas` | integer | Yes | Number of indexer pods | +| `clusterManagerRef.name` | string | Yes | Name of the `ClusterManager` CR | +| `queueRef.name` | string | No | Name of the `Queue` CR (must set both or neither) | +| `objectStorageRef.name` | string | No | Name of the `ObjectStorage` CR (must set both or neither) | -| Key | Type | Description | -| ---------- | ------- | ------------------------------------------------- | -| replicas | integer | The number of replicas (defaults to 3) | -| queueRef | corev1.ObjectReference | Message queue reference | -| objectStorageRef | corev1.ObjectReference | Object storage reference | +> **Immutable fields:** `queueRef`, `objectStorageRef` are immutable once set. -**SOK doesn't support update of queueRef and objectStorageRef.** - -**First provisioning or scaling up the number of replicas requires Indexer Cluster Splunkd restart, but this restart is implemented automatically and done by SOK.** - -## Example - -The example presented below configures IndexerCluster named indexer with Splunk ${SPLUNK_IMAGE_VERSION} image that resides in a default namespace and is scaled to 3 replicas that serve the indexing traffic. This IndexerCluster custom resource is set up with the s3-secret credentials allowing it to perform SQS and S3 operations. Queue and ObjectStorage references allow the user to specify queue and bucket settings for the indexing process. - -In this case, the setup uses the SQS and S3 based configuration where the messages are stored in and retrieved from sqs-test queue in us-west-2 region with dead letter queue set to sqs-dlq-test queue. The object storage is set to ingestion bucket in smartbus-test directory. Based on these inputs, default-mode.conf, inputs.conf and outputs.conf files are configured accordingly. - -``` +```yaml apiVersion: enterprise.splunk.com/v4 kind: ClusterManager metadata: name: cm + namespace: splunk finalizers: - enterprise.splunk.com/delete-pvc spec: - serviceAccount: ingestor-sa image: splunk/splunk:${SPLUNK_IMAGE_VERSION} + serviceAccount: ingestor-sa --- apiVersion: enterprise.splunk.com/v4 kind: IndexerCluster metadata: name: indexer + namespace: splunk finalizers: - enterprise.splunk.com/delete-pvc spec: clusterManagerRef: name: cm - serviceAccount: ingestor-sa - replicas: 3 + replicas: 3 image: splunk/splunk:${SPLUNK_IMAGE_VERSION} + serviceAccount: ingestor-sa queueRef: name: queue objectStorageRef: name: os ``` -# Common Spec - -Common spec values for all SOK Custom Resources can be found in [CustomResources doc](CustomResources.md). - -# Helm Charts - -Queue, ObjectStorage and IngestorCluster have been added to the splunk/splunk-enterprise Helm chart. IndexerCluster has also been enhanced to support new inputs. - -## Example - -Below examples describe how to define values for Queue, ObjectStorage, IngestorCluster and IndexerCluster similarly to the above yaml files specifications. - -``` -queue: - enabled: true - name: queue - provider: sqs - sqs: - name: sqs-test - authRegion: us-west-2 - endpoint: https://sqs.us-west-2.amazonaws.com - dlq: sqs-dlq-test - volumes: - - name: s3-sqs-volume - secretRef: s3-secret -``` - -``` -objectStorage: - enabled: true - name: os - provider: s3 - s3: - endpoint: https://s3.us-west-2.amazonaws.com - path: ingestion/smartbus-test -``` +--- -``` -ingestorCluster: - enabled: true - name: ingestor - replicaCount: 3 - serviceAccount: ingestor-sa - queueRef: - name: queue - objectStorageRef: - name: os -``` +## Critical User Journey -``` -clusterManager: - enabled: true - name: cm - replicaCount: 1 - serviceAccount: ingestor-sa +This section walks through the complete lifecycle from zero to a running index-ingestion-separated deployment, from the user's point of view. -indexerCluster: - enabled: true - name: indexer - replicaCount: 3 - serviceAccount: ingestor-sa - clusterManagerRef: - name: cm - queueRef: - name: queue - objectStorageRef: - name: os -``` +### Prerequisites -# Service Account +- SOK installed and running in your cluster (see [Install](Install.md)) +- An EKS cluster (or equivalent) with IAM IRSA configured, **or** static AWS credentials available in a Kubernetes Secret +- An Amazon SQS queue, dead-letter queue, and S3 bucket provisioned in AWS -To be able to configure ingestion and indexing resources correctly in a secure manner, it is required to provide these resources with the service account that is configured with a minimum set of permissions to complete required operations. With this provided, the right credentials are used by Splunk to peform its tasks. +### Step 1 — Set Up IAM Permissions -## Example +Ingestors and indexers need permission to put and receive SQS messages and to read/write the S3 bucket for oversized messages. -The example presented below configures the ingestor-sa service account by using eksctl utility. It sets up the service account for cluster-name cluster in region us-west-2 with AmazonS3FullAccess and AmazonSQSFullAccess access policies. +**Option A — IRSA (recommended for EKS):** Create a Kubernetes ServiceAccount annotated with an IAM role ARN. The role needs `AmazonSQSFullAccess` and `AmazonS3FullAccess` (or equivalent least-privilege policies). -``` -eksctl create iamserviceaccount \ +```bash +eksctl create iamserviceaccount \ --name ingestor-sa \ - --cluster ind-ing-sep-demo \ + --namespace splunk \ + --cluster my-cluster \ --region us-west-2 \ - --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess \ --attach-policy-arn arn:aws:iam::aws:policy/AmazonSQSFullAccess \ + --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess \ --approve \ --override-existing-serviceaccounts ``` -``` -$ kubectl describe sa ingestor-sa -Name: ingestor-sa -Namespace: default -Labels: app.kubernetes.io/managed-by=eksctl -Annotations: eks.amazonaws.com/role-arn: arn:aws:iam::111111111111:role/eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123 -Image pull secrets: -Mountable secrets: -Tokens: -Events: -``` - -``` -$ aws iam get-role --role-name eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123 -{ - "Role": { - "Path": "/", - "RoleName": "eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123", - "RoleId": "123456789012345678901", - "Arn": "arn:aws:iam::111111111111:role/eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123", - "CreateDate": "2025-08-07T12:03:31+00:00", - "AssumeRolePolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Federated": "arn:aws:iam::111111111111:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/1234567890123456789012345678901" - }, - "Action": "sts:AssumeRoleWithWebIdentity", - "Condition": { - "StringEquals": { - "oidc.eks.us-west-2.amazonaws.com/id/1234567890123456789012345678901:aud": "sts.amazonaws.com", - "oidc.eks.us-west-2.amazonaws.com/id/1234567890123456789012345678901:sub": "system:serviceaccount:default:ingestor-sa" - } - } - } - ] - }, - "Description": "", - "MaxSessionDuration": 3600, - "Tags": [ - { - "Key": "alpha.eksctl.io/cluster-name", - "Value": "ind-ing-sep-demo" - }, - { - "Key": "alpha.eksctl.io/iamserviceaccount-name", - "Value": "default/ingestor-sa" - }, - { - "Key": "alpha.eksctl.io/eksctl-version", - "Value": "0.211.0" - }, - { - "Key": "eksctl.cluster.k8s.io/v1alpha1/cluster-name", - "Value": "ind-ing-sep-demo" - } - ], - "RoleLastUsed": { - "LastUsedDate": "2025-08-18T08:47:27+00:00", - "Region": "us-west-2" - } - } -} -``` - -``` -$ aws iam list-attached-role-policies --role-name eksctl-cluster-name-addon-iamserviceac-Role1-123456789123 -{ - "AttachedPolicies": [ - { - "PolicyName": "AmazonSQSFullAccess", - "PolicyArn": "arn:aws:iam::aws:policy/AmazonSQSFullAccess" - }, - { - "PolicyName": "AmazonS3FullAccess", - "PolicyArn": "arn:aws:iam::aws:policy/AmazonS3FullAccess" - } - ] -} -``` - -## Documentation References - -- [IAM Roles for Service Accounts on eksctl Docs](https://eksctl.io/usage/iamserviceaccounts/) - -# Horizontal Pod Autoscaler - -To automatically adjust the number of replicas to serve the ingestion traffic effectively, it is recommended to use Horizontal Pod Autoscaler which scales the workload based on the actual demand. It enables the user to provide the metrics which are used to make decisions on removing unwanted replicas if there is not too much traffic or setting up the new ones if the traffic is too big to be handled by currently running resources. - -## Example - -The exmaple presented below configures HorizontalPodAutoscaler named ingestor-hpa that resides in a default namespace (same namespace as resources it is managing) to scale IngestorCluster custom resource named ingestor. With average utilization set to 50, the HorizontalPodAutoscaler resource will try to keep the average utilization of the pods in the scaling target at 50%. It will be able to scale the replicas starting from the minimum number of 3 with the maximum number of 10 replicas. - -``` -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: ingestor-hpa -spec: - scaleTargetRef: - apiVersion: enterprise.splunk.com/v4 - kind: IngestorCluster - name: ingestor - minReplicas: 3 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 50 -``` - -## Documentation References - -- [Horizontal Pod Autoscaling on Kubernetes Docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) - -# Grafana - -In order to monitor the resources, Grafana could be installed and configured on the cluster to present the setup on a dashabord in a series of useful diagrams and metrics. - -## Example - -In the following example, the dashboard presents ingestion and indexing data in the form of useful diagrams and metrics such as number of replicas or resource consumption. - -``` -{ - "id": null, - "uid": "splunk-autoscale", - "title": "Splunk Ingestion & Indexer Autoscaling with I/O & PV", - "schemaVersion": 27, - "version": 12, - "refresh": "5s", - "time": { "from": "now-30m", "to": "now" }, - "timezone": "browser", - "style": "dark", - "tags": ["splunk","autoscale","ingestion","indexer","io","pv"], - "graphTooltip": 1, - "panels": [ - { "id": 1, "type": "stat", "title": "Ingestion Replicas", "gridPos": {"x":0,"y":0,"w":4,"h":4}, "targets":[{"expr":"kube_statefulset_replicas{namespace=\"default\",statefulset=\"splunk-ingestor-ingestor\"}"}], "options": {"reduceOptions":{"calcs":["last"]},"orientation":"horizontal","colorMode":"value","graphMode":"none","textMode":"value","thresholds":{"mode":"absolute","steps":[{"value":null,"color":"#73BF69"},{"value":5,"color":"#EAB839"},{"value":8,"color":"#BF1B00"}]}}}, - { "id": 2, "type": "stat", "title": "Indexer Replicas", "gridPos": {"x":4,"y":0,"w":4,"h":4}, "targets":[{"expr":"kube_statefulset_replicas{namespace=\"default\",statefulset=\"splunk-indexer-indexer\"}"}], "options": {"reduceOptions":{"calcs":["last"]},"orientation":"horizontal","colorMode":"value","graphMode":"none","textMode":"value","thresholds":{"mode":"absolute","steps":[{"value":null,"color":"#73BF69"},{"value":5,"color":"#EAB839"},{"value":8,"color":"#BF1B00"}]}}}, - { "id": 3, "type": "timeseries","title": "Ingestion CPU (cores)","gridPos": {"x":8,"y":0,"w":8,"h":4},"targets":[{"expr":"sum(rate(container_cpu_usage_seconds_total{namespace=\"default\",pod=~\"splunk-ingestor-ingestor-.*\"}[1m]))","legendFormat":"CPU (cores)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#FFA600"}}}, - { "id": 4, "type": "timeseries","title": "Ingestion Memory (MiB)","gridPos": {"x":16,"y":0,"w":8,"h":4},"targets":[{"expr":"sum(container_memory_usage_bytes{namespace=\"default\",pod=~\"splunk-ingestor-ingestor-.*\"}) / 1024 / 1024","legendFormat":"Memory (MiB)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#00AF91"}}}, - { "id": 5, "type": "timeseries","title": "Ingestion Network In (KB/s)","gridPos": {"x":0,"y":8,"w":8,"h":4},"targets":[{"expr":"sum(rate(container_network_receive_bytes_total{namespace=\"default\",pod=~\"splunk-ingestor-ingestor-.*\"}[1m])) / 1024","legendFormat":"Net In (KB/s)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#59A14F"}}}, - { "id": 6, "type": "timeseries","title": "Ingestion Network Out (KB/s)","gridPos": {"x":8,"y":8,"w":8,"h":4},"targets":[{"expr":"sum(rate(container_network_transmit_bytes_total{namespace=\"default\",pod=~\"splunk-ingestor-ingestor-.*\"}[1m])) / 1024","legendFormat":"Net Out (KB/s)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#E15759"}}}, - { "id": 7, "type": "timeseries","title": "Indexer CPU (cores)","gridPos": {"x":16,"y":4,"w":8,"h":4},"targets":[{"expr":"sum(rate(container_cpu_usage_seconds_total{namespace=\"default\",pod=~\"splunk-indexer-indexer-.*\"}[1m]))","legendFormat":"CPU (cores)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#7D4E57"}}}, - { "id":8, "type": "timeseries","title": "Indexer Memory (MiB)","gridPos": {"x":0,"y":12,"w":8,"h":4},"targets":[{"expr":"sum(container_memory_usage_bytes{namespace=\"default\",pod=~\"splunk-indexer-indexer-.*\"}) / 1024 / 1024","legendFormat":"Memory (MiB)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#4E79A7"}}}, - { "id":9, "type": "timeseries","title": "Indexer Network In (KB/s)","gridPos": {"x":8,"y":12,"w":8,"h":4},"targets":[{"expr":"sum(rate(container_network_receive_bytes_total{namespace=\"default\",pod=~\"splunk-indexer-indexer-.*\"}[1m])) / 1024","legendFormat":"Net In (KB/s)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#9467BD"}}}, - { "id":10, "type": "timeseries","title": "Indexer Network Out (KB/s)","gridPos": {"x":16,"y":12,"w":8,"h":4},"targets":[{"expr":"sum(rate(container_network_transmit_bytes_total{namespace=\"default\",pod=~\"splunk-indexer-indexer-.*\"}[1m])) / 1024","legendFormat":"Net Out (KB/s)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#8C564B"}}}, - { "id":11, "type": "timeseries","title": "Ingestion Disk Read (KB/s)","gridPos": {"x":0,"y":16,"w":8,"h":4},"targets":[{"expr":"sum(rate(container_fs_reads_bytes_total{namespace=\"default\",pod=~\"splunk-ingestor-ingestor-.*\"}[1m])) / 1024","legendFormat":"Disk Read (KB/s)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#1F77B4"}}}, - { "id":12, "type": "timeseries","title": "Ingestion Disk Write (KB/s)","gridPos": {"x":8,"y":16,"w":8,"h":4},"targets":[{"expr":"sum(rate(container_fs_writes_bytes_total{namespace=\"default\",pod=~\"splunk-ingestor-ingestor-.*\"}[1m])) / 1024","legendFormat":"Disk Write (KB/s)"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"},"color":{"mode":"fixed","fixedColor":"#FF7F0E"}}}, - { "id":13, "type": "timeseries","title": "Indexer PV Usage (GiB)","gridPos": {"x":0,"y":20,"w":8,"h":4},"targets":[{"expr":"kubelet_volume_stats_used_bytes{namespace=\"default\",persistentvolumeclaim=~\".*-indexer-.*\"} / 1024 / 1024 / 1024","legendFormat":"Used GiB"},{"expr":"kubelet_volume_stats_capacity_bytes{namespace=\"default\",persistentvolumeclaim=~\".*-indexer-.*\"} / 1024 / 1024 / 1024","legendFormat":"Capacity GiB"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"}}}, - { "id":14, "type": "timeseries","title": "Ingestion PV Usage (GiB)","gridPos": {"x":8,"y":20,"w":8,"h":4},"targets":[{"expr":"kubelet_volume_stats_used_bytes{namespace=\"default\",persistentvolumeclaim=~\".*-ingestor-.*\"} / 1024 / 1024 / 1024","legendFormat":"Used GiB"},{"expr":"kubelet_volume_stats_capacity_bytes{namespace=\"default\",persistentvolumeclaim=~\".*-ingestor-.*\"} / 1024 / 1024 / 1024","legendFormat":"Capacity GiB"}],"options":{"legend":{"displayMode":"list","placement":"bottom"},"yAxis":{"mode":"auto"}}} - ] -} -``` - -## Documentation References - -- [kube-prometheus-stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) - -# App Installation for Ingestor Cluster Instances - -Application installation is supported for Ingestor Cluster instances. However, as of now, applications are installed using local scope and if any application requires Splunk restart, there is no automated way to detect it and trigger automatically via Splunk Operator. - -Therefore, to be able to enforce Splunk restart for each of the Ingestor Cluster pods, it is recommended to add/update IngestorCluster CR annotations/labels and apply the new configuration which will trigger the rolling restart of Splunk pods for Ingestor Cluster. - -Ideally, update of annotations and labels should not trigger pod restart at all and it is under the investigation on how to stop this from happening and handle restart automatically. - -# Example - -1. Install CRDs and Splunk Operator for Kubernetes. - -- SOK_IMAGE_VERSION: version of the image for Splunk Operator for Kubernetes - -``` -$ make install -``` - -``` -$ kubectl apply -f ${SOK_IMAGE_VERSION}/splunk-operator-cluster.yaml --server-side -``` +Verify the ServiceAccount is annotated with the role ARN: -``` -$ kubectl get po -n splunk-operator -NAME READY STATUS RESTARTS AGE -splunk-operator-controller-manager-785b89d45c-dwfkd 2/2 Running 0 4d3h +```bash +kubectl describe sa ingestor-sa -n splunk +# Annotations: eks.amazonaws.com/role-arn: arn:aws:iam::111111111111:role/... ``` -2. Create a service account. +**Option B — Static credentials:** Create a Kubernetes Secret with `s3_access_key` and `s3_secret_key` keys. Reference this secret in `Queue.spec.sqs.volumes`. No ServiceAccount annotation is needed. -``` -$ eksctl create iamserviceaccount \ - --name ingestor-sa \ - --cluster ind-ing-sep-demo \ - --region us-west-2 \ - --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess \ - --attach-policy-arn arn:aws:iam::aws:policy/AmazonSQSFullAccess \ - --approve \ - --override-existing-serviceaccounts -``` - -``` -$ kubectl describe sa ingestor-sa -Name: ingestor-sa -Namespace: default -Labels: app.kubernetes.io/managed-by=eksctl -Annotations: eks.amazonaws.com/role-arn: arn:aws:iam::111111111111:role/eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123 -Image pull secrets: -Mountable secrets: -Tokens: -Events: -``` - -``` -$ aws iam get-role --role-name eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123 -{ - "Role": { - "Path": "/", - "RoleName": "eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123", - "RoleId": "123456789012345678901", - "Arn": "arn:aws:iam::111111111111:role/eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123", - "CreateDate": "2025-08-07T12:03:31+00:00", - "AssumeRolePolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Federated": "arn:aws:iam::111111111111:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/1234567890123456789012345678901" - }, - "Action": "sts:AssumeRoleWithWebIdentity", - "Condition": { - "StringEquals": { - "oidc.eks.us-west-2.amazonaws.com/id/1234567890123456789012345678901:aud": "sts.amazonaws.com", - "oidc.eks.us-west-2.amazonaws.com/id/1234567890123456789012345678901:sub": "system:serviceaccount:default:ingestor-sa" - } - } - } - ] - }, - "Description": "", - "MaxSessionDuration": 3600, - "Tags": [ - { - "Key": "alpha.eksctl.io/cluster-name", - "Value": "ind-ing-sep-demo" - }, - { - "Key": "alpha.eksctl.io/iamserviceaccount-name", - "Value": "default/ingestor-sa" - }, - { - "Key": "alpha.eksctl.io/eksctl-version", - "Value": "0.211.0" - }, - { - "Key": "eksctl.cluster.k8s.io/v1alpha1/cluster-name", - "Value": "ind-ing-sep-demo" - } - ], - "RoleLastUsed": { - "LastUsedDate": "2025-08-18T08:47:27+00:00", - "Region": "us-west-2" - } - } -} +```bash +kubectl create secret generic s3-secret \ + --from-literal=s3_access_key=AKIAIOSFODNN7EXAMPLE \ + --from-literal=s3_secret_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \ + -n splunk ``` -``` -$ aws iam list-attached-role-policies --role-name eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123 -{ - "AttachedPolicies": [ - { - "PolicyName": "AmazonSQSFullAccess", - "PolicyArn": "arn:aws:iam::aws:policy/AmazonSQSFullAccess" - }, - { - "PolicyName": "AmazonS3FullAccess", - "PolicyArn": "arn:aws:iam::aws:policy/AmazonS3FullAccess" - } - ] -} -``` +### Step 2 — Create the Queue CR -3. Install Queue resource. +Tell SOK about your SQS queue. The Queue CR is a shared reference — both the IngestorCluster and IndexerCluster will point to it. -``` -$ cat queue.yaml +```bash +kubectl apply -f - < -Annotations: -API Version: enterprise.splunk.com/v4 -Kind: Queue -Metadata: - Creation Timestamp: 2025-10-27T10:25:53Z - Finalizers: - enterprise.splunk.com/delete-pvc - Generation: 1 - Resource Version: 12345678 - UID: 12345678-1234-5678-1234-012345678911 -Spec: - Sqs: - Auth Region: us-west-2 - DLQ: sqs-dlq-test - Endpoint: https://sqs.us-west-2.amazonaws.com - Name: sqs-test - Provider: sqs -Status: - Message: - Phase: Ready - Resource Rev Map: -Events: -``` - -4. Install ObjectStorage resource. +Tell SOK about your S3 bucket for oversized messages. -``` -$ cat os.yaml +```bash +kubectl apply -f - < -Annotations: -API Version: enterprise.splunk.com/v4 -Kind: ObjectStorage -Metadata: - Creation Timestamp: 2025-10-27T10:25:53Z - Finalizers: - enterprise.splunk.com/delete-pvc - Generation: 1 - Resource Version: 12345678 - UID: 12345678-1234-5678-1234-012345678911 -Spec: - S3: - Endpoint: https://s3.us-west-2.amazonaws.com - Path: ingestion/smartbus-test - Provider: s3 -Status: - Message: - Phase: Ready - Resource Rev Map: -Events: -``` +### Step 4 — Deploy the IngestorCluster -5. Install IngestorCluster resource. +SOK will create the ingestor StatefulSet. On first boot, the operator builds the queue config ConfigMap and each pod's init container writes the Splunk app before Splunk starts. -``` -$ cat ingestor.yaml +```bash +kubectl apply -f - < -Annotations: -API Version: enterprise.splunk.com/v4 -Kind: IngestorCluster -Metadata: - Creation Timestamp: 2025-08-18T09:49:45Z - Generation: 1 - Resource Version: 12345678 - UID: 12345678-1234-1234-1234-1234567890123 -Spec: - Queue Ref: - Name: queue - Namespace: default - Image: splunk/splunk:${SPLUNK_IMAGE_VERSION} - Object Storage Ref: - Name: os - Namespace: default - Replicas: 3 - Service Account: ingestor-sa -Status: - App Context: - App Repo: - App Install Period Seconds: 90 - Defaults: - Premium Apps Props: - Es Defaults: - Install Max Retries: 2 - Bundle Push Status: - Is Deployment In Progress: false - Last App Info Check Time: 0 - Version: 0 - Credential Secret Version: 33744270 - Message: - Phase: Ready - Ready Replicas: 3 - Replicas: 3 - Resource Rev Map: - Selector: app.kubernetes.io/instance=splunk-ingestor-ingestor - Tel App Installed: true -Events: -``` - -``` -$ kubectl exec -it splunk-ingestor-ingestor-0 -- sh -$ kubectl exec -it splunk-ingestor-ingestor-1 -- sh -$ kubectl exec -it splunk-ingestor-ingestor-2 -- sh -sh-4.4$ env | grep AWS -AWS_DEFAULT_REGION=us-west-2 -AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token -AWS_REGION=us-west-2 -AWS_ROLE_ARN=arn:aws:iam::111111111111:role/eksctl-ind-ing-sep-demo-addon-iamserviceac-Role1-123456789123 -AWS_STS_REGIONAL_ENDPOINTS=regional -sh-4.4$ cat /opt/splunk/etc/system/local/default-mode.conf -[pipeline:remotequeueruleset] -disabled = false - -[pipeline:ruleset] -disabled = true - -[pipeline:remotequeuetyping] -disabled = false - -[pipeline:remotequeueoutput] -disabled = false - -[pipeline:typing] -disabled = true - -[pipeline:indexerPipe] -disabled = true - -sh-4.4$ cat /opt/splunk/etc/system/local/outputs.conf -[remote_queue:sqs-test] -remote_queue.sqs_smartbus.max_count.max_retries_per_part = 4 -remote_queue.sqs_smartbus.auth_region = us-west-2 -remote_queue.sqs_smartbus.dead_letter_queue.name = sqs-dlq-test -remote_queue.sqs_smartbus.encoding_format = s2s -remote_queue.sqs_smartbus.endpoint = https://sqs.us-west-2.amazonaws.com -remote_queue.sqs_smartbus.large_message_store.endpoint = https://s3.us-west-2.amazonaws.com -remote_queue.sqs_smartbus.large_message_store.path = s3://ingestion/smartbus-test -remote_queue.sqs_smartbus.retry_policy = max_count -remote_queue.sqs_smartbus.send_interval = 5s -remote_queue.type = sqs_smartbus -``` +### Step 5 — Deploy the Indexer Cluster -6. Install IndexerCluster resource. - -``` -$ cat idxc.yaml +```bash +kubectl apply -f - </50% 3 10 0 10s -``` +### Scaling Ingestors -``` -kubectl top pod -NAME CPU(cores) MEMORY(bytes) -hec-locust-load-29270124-f86gj 790m 221Mi -splunk-cm-cluster-manager-0 154m 1696Mi -splunk-indexer-indexer-0 107m 1339Mi -splunk-indexer-indexer-1 187m 1052Mi -splunk-indexer-indexer-2 203m 1703Mi -splunk-ingestor-ingestor-0 97m 517Mi -splunk-ingestor-ingestor-1 64m 585Mi -splunk-ingestor-ingestor-2 57m 565Mi -``` +To handle more ingestion throughput, increase replicas. New pods pick up the existing ConfigMap automatically — no reconfiguration is needed. -``` -$ kubectl get po -NAME READY STATUS RESTARTS AGE -hec-locust-load-29270126-szgv2 1/1 Running 0 30s -splunk-cm-cluster-manager-0 1/1 Running 0 41m -splunk-indexer-indexer-0 1/1 Running 0 38m -splunk-indexer-indexer-1 1/1 Running 0 38m -splunk-indexer-indexer-2 1/1 Running 0 38m -splunk-ingestor-ingestor-0 1/1 Running 0 53m -splunk-ingestor-ingestor-1 1/1 Running 0 55m -splunk-ingestor-ingestor-2 1/1 Running 0 57m -splunk-ingestor-ingestor-3 0/1 Running 0 116s -splunk-ingestor-ingestor-4 0/1 Running 0 116s +```bash +kubectl patch ingestorcluster ingestor -n splunk \ + --type=merge -p '{"spec":{"replicas":5}}' ``` -``` -kubectl top pod -NAME CPU(cores) MEMORY(bytes) -hec-locust-load-29270126-szgv2 532m 72Mi -splunk-cm-cluster-manager-0 91m 1260Mi -splunk-indexer-indexer-0 112m 865Mi -splunk-indexer-indexer-1 115m 855Mi -splunk-indexer-indexer-2 152m 1696Mi -splunk-ingestor-ingestor-0 115m 482Mi -splunk-ingestor-ingestor-1 76m 496Mi -splunk-ingestor-ingestor-2 156m 553Mi -splunk-ingestor-ingestor-3 355m 846Mi -splunk-ingestor-ingestor-4 1036m 979Mi -``` +### Scaling Indexers -``` -kubectl get hpa -NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE -ing-hpa IngestorCluster/ingestor cpu: 115%/50% 3 10 10 8m54s +```bash +kubectl patch indexercluster indexer -n splunk \ + --type=merge -p '{"spec":{"replicas":5}}' ``` -8. Generate fake load. +### Rotating Credentials (Static Credential Mode) -- HEC_TOKEN: HEC token for making fake calls +Update the Kubernetes Secret referenced in `Queue.spec.sqs.volumes`. SOK detects the Secret's ResourceVersion change on the next reconcile, rebuilds the ConfigMap with new credentials, and triggers a rolling restart of ingestor pods. +```bash +kubectl create secret generic s3-secret \ + --from-literal=s3_access_key=NEW_ACCESS_KEY \ + --from-literal=s3_secret_key=NEW_SECRET_KEY \ + -n splunk \ + --dry-run=client -o yaml | kubectl apply -f - ``` -$ kubectl get secret splunk-default-secret -o yaml -apiVersion: v1 -data: - hec_token: HEC_TOKEN - idxc_secret: YWJjZGVmMTIzNDU2Cg== - pass4SymmKey: YWJjZGVmMTIzNDU2Cg== - password: YWJjZGVmMTIzNDU2Cg== - shc_secret: YWJjZGVmMTIzNDU2Cg== -kind: Secret -metadata: - creationTimestamp: "2025-08-26T10:15:11Z" - name: splunk-default-secret - namespace: default - ownerReferences: - - apiVersion: enterprise.splunk.com/v4 - controller: false - kind: IngestorCluster - name: ingestor - uid: 12345678-1234-1234-1234-1234567890123 - - apiVersion: enterprise.splunk.com/v4 - controller: false - kind: ClusterManager - name: cm - uid: 12345678-1234-1234-1234-1234567890125 - - apiVersion: enterprise.splunk.com/v4 - controller: false - kind: IndexerCluster - name: indexer - uid: 12345678-1234-1234-1234-1234567890124 - resourceVersion: "123456" - uid: 12345678-1234-1234-1234-1234567890126 -type: Opaque -``` +### Pausing Reconciliation + +To temporarily prevent SOK from making changes to an IngestorCluster (e.g. during a maintenance window): + +```bash +kubectl annotate ingestorcluster ingestor -n splunk \ + ingestorcluster.enterprise.splunk.com/paused=true ``` -$ echo HEC_TOKEN | base64 -d -HEC_TOKEN + +Remove the annotation to resume: +```bash +kubectl annotate ingestorcluster ingestor -n splunk \ + ingestorcluster.enterprise.splunk.com/paused- ``` +### Deploying Apps to Ingestors + +Use the `appRepo` field on the IngestorCluster spec to install Splunk apps via the App Framework. See [AppFramework](AppFramework.md) for configuration details. + +### Deleting the Deployment + +Delete in reverse dependency order to allow SOK to cleanly remove finalizers and deregister resources: + +```bash +kubectl delete ingestorcluster ingestor -n splunk +kubectl delete indexercluster indexer -n splunk +kubectl delete clustermanager cm -n splunk +kubectl delete objectstorage os -n splunk +kubectl delete queue queue -n splunk ``` -cat loadgen.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hec-locust-config -data: - requirements.txt: | - locust - requests - urllib3 - - locustfile.py: | - import urllib3 - from locust import HttpUser, task, between - - # disable insecure‐ssl warnings - urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - - class HECUser(HttpUser): - wait_time = between(1, 2) - # use HTTPS and explicit port - host = "https://splunk-ingestor-ingestor-service:8088" - - def on_start(self): - # turn off SSL cert verification - self.client.verify = False - - @task - def send_event(self): - token = "HEC_TOKEN" - headers = { - "Authorization": f"Splunk {token}", - "Content-Type": "application/json" - } - payload = {"event": {"message": "load test", "value": 123}} - # this will POST to https://…:8088/services/collector/event - self.client.post( - "/services/collector/event", - json=payload, - headers=headers, - name="HEC POST" - ) + --- -apiVersion: batch/v1 -kind: CronJob -metadata: - name: hec-locust-load -spec: - schedule: "*/2 * * * *" - concurrencyPolicy: Replace - startingDeadlineSeconds: 60 - jobTemplate: - spec: - backoffLimit: 1 - template: - spec: - containers: - - name: locust - image: python:3.9-slim - command: - - sh - - -c - - | - pip install --no-cache-dir -r /app/requirements.txt \ - && exec locust \ - -f /app/locustfile.py \ - --headless \ - -u 200 \ - -r 50 \ - --run-time 1m50s - volumeMounts: - - name: app - mountPath: /app - restartPolicy: OnFailure - volumes: - - name: app - configMap: - name: hec-locust-config - defaultMode: 0755 -``` -``` -kubectl apply -f loadgen.yaml -``` +## Troubleshooting +### Ingestor pods stuck in Init state + +The init container `init-ingestor-queue-config` failed to run. Check why: + +```bash +kubectl describe pod splunk-ingestor-ingestor-0 -n splunk | grep -A 10 "Init Containers" +kubectl logs splunk-ingestor-ingestor-0 -n splunk -c init-ingestor-queue-config ``` -$ kubectl get cm -NAME DATA AGE -hec-locust-config 2 10s -kube-root-ca.crt 1 5d2h -splunk-cluster-manager-cm-configmap 1 28m -splunk-default-probe-configmap 3 58m -splunk-indexer-indexer-configmap 1 28m -splunk-ingestor-ingestor-configmap 1 48m -``` +Common causes: +- The ConfigMap `splunk-ingestor-ingestor-queue-config` was not yet created (wait for operator reconcile) +- The `serviceAccount` does not exist in the namespace + +### Queue config ConfigMap not found + +Verify the ConfigMap was created: +```bash +kubectl get cm splunk-ingestor-ingestor-queue-config -n splunk -o yaml ``` -$ kubectl get cj -NAME SCHEDULE TIMEZONE SUSPEND ACTIVE LAST SCHEDULE AGE -hec-locust-load */2 * * * * False 1 2s 26s + +If missing, check operator logs for errors from `buildAndApplyIngestorQueueConfigMap`: +```bash +kubectl logs -n splunk-operator deployment/splunk-operator-controller-manager | grep -i "ingestor-queue-config" ``` +### Ingestors cannot reach SQS + +Check that the pod's ServiceAccount has the correct IAM role annotation and that the role policy includes SQS permissions: +```bash +kubectl describe pod splunk-ingestor-ingestor-0 -n splunk | grep -i "service-account\|role-arn" ``` -$ kubectl get po -NAME READY STATUS RESTARTS AGE -hec-locust-load-29270114-zq7zz 1/1 Running 0 15s -splunk-cm-cluster-manager-0 1/1 Running 0 29m -splunk-indexer-indexer-0 1/1 Running 0 26m -splunk-indexer-indexer-1 1/1 Running 0 26m -splunk-indexer-indexer-2 1/1 Running 0 26m -splunk-ingestor-ingestor-0 1/1 Running 0 41m -splunk-ingestor-ingestor-1 1/1 Running 0 43m -splunk-ingestor-ingestor-2 1/1 Running 0 45m + +### Status and events + +```bash +# Overall status +kubectl get ingestorcluster,indexercluster,queue,objectstorage -n splunk + +# Detailed status with conditions and events +kubectl describe ingestorcluster ingestor -n splunk + +# Operator logs +kubectl logs -n splunk-operator deployment/splunk-operator-controller-manager --tail=100 ``` +--- + +## Helm Chart + +Queue, ObjectStorage, and IngestorCluster are included in the `splunk/splunk-enterprise` Helm chart. IndexerCluster has been extended with `queueRef` and `objectStorageRef` inputs. + +```yaml +queue: + enabled: true + name: queue + provider: sqs + sqs: + name: sqs-smartbus + authRegion: us-west-2 + dlq: sqs-smartbus-dlq + volumes: + - name: s3-sqs-creds + secretRef: s3-secret + +objectStorage: + enabled: true + name: os + provider: s3 + s3: + endpoint: https://s3.us-west-2.amazonaws.com + path: s3://my-smartbus-bucket/ingestion + +ingestorCluster: + enabled: true + name: ingestor + replicaCount: 3 + serviceAccount: ingestor-sa + queueRef: + name: queue + objectStorageRef: + name: os + +clusterManager: + enabled: true + name: cm + serviceAccount: ingestor-sa + +indexerCluster: + enabled: true + name: indexer + replicaCount: 3 + serviceAccount: ingestor-sa + clusterManagerRef: + name: cm + queueRef: + name: queue + objectStorageRef: + name: os ``` -$ aws s3 ls s3://ingestion/smartbus-test/ - PRE 29DDC1B4-D43E-47D1-AC04-C87AC7298201/ - PRE 43E16731-7146-4397-8553-D68B5C2C8634/ - PRE C8A4D060-DE0D-4DCB-9690-01D8902825DC/ -``` \ No newline at end of file + +--- + +## Reference + +- [Custom Resources](CustomResources.md) — CommonSplunkSpec fields shared by all CRs +- [App Framework](AppFramework.md) — Deploying Splunk apps to ingestor pods +- [SmartStore](SmartStore.md) — S3-backed index storage (separate from ingestion S3 bucket) +- [Security](Security.md) — RBAC, pod security, network policies diff --git a/docs/images/index_ingestion_separation.png b/docs/images/index_ingestion_separation.png new file mode 100644 index 0000000000000000000000000000000000000000..e9db394b92d7e8e6421b04a5ff38432cf44eb376 GIT binary patch literal 305310 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%0A?s()#v@7k0d%VcD9Qm1;8H1Xz`{UB^k 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ˆZHL2&cWNtXqxhaK}f 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