diff --git a/.env b/.env index 9d59fde8e..d79c25287 100644 --- a/.env +++ b/.env @@ -1,9 +1,9 @@ -OPERATOR_SDK_VERSION=v1.28.1 -REVIEWERS=smohan-splunk,sgontla,gaurav-splunk,vivekr-splunk,kumarajeet -GO_VERSION=1.19.2 +OPERATOR_SDK_VERSION=v1.31.0 +REVIEWERS=vivekr-splunk,akondur +GO_VERSION=1.21.5 AWSCLI_URL=https://awscli.amazonaws.com/awscli-exe-linux-x86_64-2.8.6.zip -KUBECTL_VERSION=v1.28.0 +KUBECTL_VERSION=v1.29.1 AZ_CLI_VERSION=2.30.0 EKSCTL_VERSION=v0.143.0 -EKS_CLUSTER_K8_VERSION=1.26 -SPLUNK_ENTERPRISE_RELEASE_IMAGE=splunk/splunk:9.1.1 +EKS_CLUSTER_K8_VERSION=1.27 +SPLUNK_ENTERPRISE_RELEASE_IMAGE=splunk/splunk:9.1.3 diff --git a/.github/workflows/docs-pages.yml b/.github/workflows/docs-pages.yml new file mode 100644 index 000000000..0c5cd93f8 --- /dev/null +++ b/.github/workflows/docs-pages.yml @@ -0,0 +1,70 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# Sample workflow for building and deploying a Jekyll site to GitHub Pages +name: Deploy Jekyll site to Pages + +on: + push: + branches: ["main"] + paths: + - "docs/**" + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + # Build job + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: docs + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.1' # Not needed with a .ruby-version file + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + cache-version: 0 # Increment this number if you need to re-download cached gems + working-directory: '${{ github.workspace }}/docs' + - name: Setup Pages + id: pages + uses: actions/configure-pages@v3 + - name: Build with Jekyll + # Outputs to the './_site' directory by default + run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" + env: + JEKYLL_ENV: production + - name: Upload artifact + # Automatically uploads an artifact from the './_site' directory by default + uses: actions/upload-pages-artifact@v1 + with: + path: "docs/_site/" + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 \ No newline at end of file diff --git a/.github/workflows/int-test-workflow.yml b/.github/workflows/int-test-workflow.yml index 17b34ff19..3ee2f4761 100644 --- a/.github/workflows/int-test-workflow.yml +++ b/.github/workflows/int-test-workflow.yml @@ -8,6 +8,7 @@ on: jobs: build-operator-image: runs-on: ubuntu-latest + timeout-minutes: 360 env: SPLUNK_ENTERPRISE_IMAGE: ${{ secrets.SPLUNK_ENTERPRISE_IMAGE }} SPLUNK_OPERATOR_IMAGE_NAME: splunk/splunk-operator diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ffd713373..b4e885e98 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,6 +21,6 @@ jobs: uses: helm/chart-releaser-action@v1.4.0 with: charts_dir: helm-charts - config: docs/cr.yaml + config: docs/_helm/cr.yaml env: CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" \ No newline at end of file diff --git a/Makefile b/Makefile index dd59513ae..359648d7d 100644 --- a/Makefile +++ b/Makefile @@ -3,17 +3,17 @@ # To re-generate a bundle for another specific version without changing the standard setup, you can: # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) -VERSION ?= 2.2.1 +VERSION ?= 2.5.0 # SPLUNK_ENTERPRISE_IMAGE defines the splunk docker tag that is used as default image. SPLUNK_ENTERPRISE_IMAGE ?= "docker.io/splunk/splunk:edge" # WATCH_NAMESPACE defines if its clusterwide operator or namespace specific -# by default we leave it as clusterwide if it has to be namespace specific, +# by default we leave it as clusterwide if it has to be namespace specific, # add namespace to this WATCH_NAMESPACE ?= "" -# NAMESPACE defines default namespace where operator will be installed +# NAMESPACE defines default namespace where operator will be installed NAMESPACE ?= "splunk-operator" # CHANNELS define the bundle channels used in the bundle. diff --git a/README.md b/README.md index 8a1003593..ba00a0ad9 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ This repository is used to build the Splunk [Operator](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) for Kubernetes (SOK). If you are just looking for documentation on how to deploy and use the latest release, please see the -[Getting Started Documentation](docs/README.md). +[Getting Started Documentation](https://splunk.github.io/splunk-operator/). ## Prerequisites diff --git a/bundle/manifests/splunk-operator.clusterserviceversion.yaml b/bundle/manifests/splunk-operator.clusterserviceversion.yaml index 60e390188..31a34c49f 100644 --- a/bundle/manifests/splunk-operator.clusterserviceversion.yaml +++ b/bundle/manifests/splunk-operator.clusterserviceversion.yaml @@ -111,7 +111,7 @@ metadata: capabilities: Seamless Upgrades categories: Big Data, Logging & Tracing, Monitoring, Security, AI/Machine Learning containerImage: splunk/splunk-operator@sha256:c4e0d314622699496f675760aad314520d050a66627fdf33e1e21fa28ca85d50 - createdAt: "2023-10-06T22:35:48Z" + createdAt: "2024-01-22T21:05:16Z" description: The Splunk Operator for Kubernetes enables you to quickly and easily deploy Splunk Enterprise on your choice of private or public cloud provider. The Operator simplifies scaling and management of Splunk Enterprise by automating @@ -788,8 +788,15 @@ spec: memory: 64Mi securityContext: allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault - args: - --leader-elect - --pprof @@ -801,14 +808,14 @@ spec: fieldRef: fieldPath: metadata.annotations['olm.targetNamespaces'] - name: RELATED_IMAGE_SPLUNK_ENTERPRISE - value: docker.io/splunk/splunk:9.1.1 + value: docker.io/splunk/splunk:9.1.3 - name: OPERATOR_NAME value: splunk-operator - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - image: docker.io/splunk/splunk-operator:2.4.0 + image: docker.io/splunk/splunk-operator:2.5.0 imagePullPolicy: Always livenessProbe: httpGet: @@ -832,8 +839,15 @@ spec: memory: 2000Mi securityContext: allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /opt/splunk/appframework/ name: app-staging @@ -913,7 +927,7 @@ spec: name: Splunk Inc. url: www.splunk.com relatedImages: - - image: docker.io/splunk/splunk:9.1.1 + - image: docker.io/splunk/splunk:9.1.3 name: splunk-enterprise replaces: splunk-operator.v2.2.0 version: 2.2.1 diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index c9f04f6c6..5e0a5b0b4 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -124,7 +124,7 @@ patches: - name: WATCH_NAMESPACE value: WATCH_NAMESPACE_VALUE - name: RELATED_IMAGE_SPLUNK_ENTERPRISE - value: docker.io/splunk/splunk:9.1.1 + value: docker.io/splunk/splunk:9.1.3 - name: OPERATOR_NAME value: splunk-operator - name: POD_NAME diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml index 908875e3a..2d31fa4ec 100644 --- a/config/default/manager_auth_proxy_patch.yaml +++ b/config/default/manager_auth_proxy_patch.yaml @@ -18,6 +18,13 @@ spec: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true + capabilities: + drop: + - "ALL" + add: + - "NET_BIND_SERVICE" + seccompProfile: + type: "RuntimeDefault" image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.1 args: - "--secure-listen-address=0.0.0.0:8443" diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 1feed3a3b..d367eb1a7 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -17,4 +17,4 @@ kind: Kustomization images: - name: controller newName: docker.io/splunk/splunk-operator - newTag: 2.4.0 + newTag: 2.5.0 diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 4748fb982..bd5e4a588 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -17,7 +17,7 @@ spec: matchLabels: control-plane: controller-manager name: splunk-operator - strategy: + strategy: type: Recreate replicas: 1 template: @@ -54,6 +54,13 @@ spec: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true + capabilities: + drop: + - "ALL" + add: + - "NET_BIND_SERVICE" + seccompProfile: + type: "RuntimeDefault" livenessProbe: httpGet: path: /healthz diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..f40fbd8ba --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,5 @@ +_site +.sass-cache +.jekyll-cache +.jekyll-metadata +vendor diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 000000000..086a5c9ea --- /dev/null +++ b/docs/404.html @@ -0,0 +1,25 @@ +--- +permalink: /404.html +layout: default +--- + + + +
+

404

+ +

Page not found :(

+

The requested page could not be found.

+
diff --git a/docs/CustomResources.md b/docs/CustomResources.md deleted file mode 100644 index 387858c28..000000000 --- a/docs/CustomResources.md +++ /dev/null @@ -1,352 +0,0 @@ -# Custom Resource Guide - -The Splunk Operator provides a collection of -[custom resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) -you can use to manage Splunk Enterprise deployments in your Kubernetes cluster. - -- [Custom Resource Guide](#custom-resource-guide) - - [Metadata Parameters](#metadata-parameters) - - [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources) - - [Common Spec Parameters for Splunk Enterprise Resources](#common-spec-parameters-for-splunk-enterprise-resources) - - [LicenseManager Resource Spec Parameters](#licensemanager-resource-spec-parameters) - - [Standalone Resource Spec Parameters](#standalone-resource-spec-parameters) - - [SearchHeadCluster Resource Spec Parameters](#searchheadcluster-resource-spec-parameters) - - [ClusterManager Resource Spec Parameters](#clustermanager-resource-spec-parameters) - - [IndexerCluster Resource Spec Parameters](#indexercluster-resource-spec-parameters) - - [MonitoringConsole Resource Spec Parameters](#monitoringconsole-resource-spec-parameters) - - [Examples of Guaranteed and Burstable QoS](#examples-of-guaranteed-and-burstable-qos) - - [A Guaranteed QoS Class example:](#a-guaranteed-qos-class-example) - - [A Burstable QoS Class example:](#a-burstable-qos-class-example) - - [A BestEffort QoS Class example:](#a-besteffort-qos-class-example) - - [Pod Resources Management](#pod-resources-management) - -For examples on how to use these custom resources, please see -[Configuring Splunk Enterprise Deployments](Examples.md). - - -## Metadata Parameters - -All resources in Kubernetes include a `metadata` section. You can use this -to define a name for a specific instance of the resource, and which namespace -you would like the resource to reside within: - -| Key | Type | Description | -| --------- | ------ | ----------------------------------------------------------------------------------------------------------- | -| name | string | Each instance of your resource is distinguished using this name. | -| namespace | string | Your instance will be created within this namespace. You must ensure that this namespace exists beforehand. | - -If you do not provide a `namespace`, you current context will be used. - -```yaml -apiVersion: enterprise.splunk.com/v4 -kind: Standalone -metadata: - name: s1 - namespace: splunk - finalizers: - - enterprise.splunk.com/delete-pvc -``` - -The `enterprise.splunk.com/delete-pvc` finalizer is optional, and may be -used to tell the Splunk Operator that you would like it to remove all the -[Persistent Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) -associated with the instance when you delete it. - - -## Common Spec Parameters for All Resources - -```yaml -apiVersion: enterprise.splunk.com/v4 -kind: Standalone -metadata: - annotations: - service.beta.kubernetes.io/azure-load-balancer-internal: "true" - name: example -spec: - imagePullPolicy: Always - livenessInitialDelaySeconds: 400 - readinessInitialDelaySeconds: 390 - serviceTemplate: - spec: - type: LoadBalancer - topologySpreadConstraints: - - maxSkew: 1 - topologyKey: zone - whenUnsatisfiable: DoNotSchedule - labelSelector: - matchLabels: - foo: bar - extraEnv: - - name: ADDITIONAL_ENV_VAR_1 - value: "test_value_1" - - name: ADDITIONAL_ENV_VAR_2 - value: "test_value_2" - resources: - requests: - memory: "512Mi" - cpu: "0.1" - limits: - memory: "8Gi" - cpu: "4" -``` - -The `spec` section is used to define the desired state for a resource. All -custom resources provided by the Splunk Operator include the following -configuration parameters: - -| Key | Type | Description | -| --------------------- | ---------- | ---------------------------------------------------------------------------------------------------------- | -| image | string | Container image to use for pod instances (overrides `RELATED_IMAGE_SPLUNK_ENTERPRISE` environment variable | -| imagePullPolicy | string | Sets pull policy for all images (either "Always" or the default: "IfNotPresent") | -| livenessInitialDelaySeconds | number | Sets the initialDelaySeconds for Liveness probe (default: 300) | -| readinessInitialDelaySeconds | number | Sets the initialDelaySeconds for Readiness probe (default: 10) | -| extraEnv | [EnvVar](https://v1-17.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvar-v1-core) | Sets the extra environment variables to be passed to the Splunk instance containers. WARNING: Setting environment variables used by Splunk or Ansible will affect Splunk installation and operation | -| schedulerName | string | Name of [Scheduler](https://kubernetes.io/docs/concepts/scheduling/kube-scheduler/) to use for pod placement (defaults to "default-scheduler") | -| affinity | [Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#affinity-v1-core) | [Kubernetes Affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) rules that control how pods are assigned to particular nodes | -| resources | [ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#resourcerequirements-v1-core) | The settings for allocating [compute resource requirements](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to use for each pod instance. The default settings should be considered for demo/test purposes. Please see [Hardware Resource Requirements](https://github.com/splunk/splunk-operator/blob/develop/docs/README.md#hardware-resources-requirements) for production values.| -| serviceTemplate | [Service](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#service-v1-core) | Template used to create Kubernetes [Services](https://kubernetes.io/docs/concepts/services-networking/service/) | -| topologySpreadConstraint | [TopologySpreadConstraint](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/) | Template used to create Kubernetes [TopologySpreadConstraint](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/) | - -## Common Spec Parameters for Splunk Enterprise Resources - -```yaml -apiVersion: enterprise.splunk.com/v4 -kind: Standalone -metadata: - name: example -spec: - etcVolumeStorageConfig: - storageClassName: gp2 - storageCapacity: 15Gi - varVolumeStorageConfig: - storageClassName: customStorageClass - storageCapacity: 25Gi - volumes: - - name: licenses - configMap: - name: splunk-licenses - licenseManagerRef: - name: example - clusterManagerRef: - name: example - serviceAccount: custom-serviceaccount -``` - -The following additional configuration parameters may be used for all Splunk -Enterprise resources, including: `Standalone`, `LicenseManager`, -`SearchHeadCluster`, `ClusterManager` and `IndexerCluster`: - -| Key | Type | Description | -| ------------------ | ------- | ----------------------------------------------------------------------------- | -| etcVolumeStorageConfig | StorageClassSpec | Storage class spec for Splunk etc volume as described in [StorageClass](StorageClass.md) | -| varVolumeStorageConfig | StorageClassSpec | Storage class spec for Splunk var volume as described in [StorageClass](StorageClass.md) | -| volumes | [Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#volume-v1-core) | List of one or more [Kubernetes volumes](https://kubernetes.io/docs/concepts/storage/volumes/). These will be mounted in all container pods as as `/mnt/` | -| defaults | string | Inline map of [default.yml](https://github.com/splunk/splunk-ansible/blob/develop/docs/advanced/default.yml.spec.md) overrides used to initialize the environment | -| defaultsUrl | string | Full path or URL for one or more [default.yml](https://github.com/splunk/splunk-ansible/blob/develop/docs/advanced/default.yml.spec.md) files, separated by commas | -| licenseUrl | string | Full path or URL for a Splunk Enterprise license file | -| licenseManagerRef | [ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectreference-v1-core) | Reference to a Splunk Operator managed `LicenseManager` instance (via `name` and optionally `namespace`) to use for licensing | -| clusterManagerRef | [ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectreference-v1-core) | Reference to a Splunk Operator managed `ClusterManager` instance (via `name` and optionally `namespace`) to use for indexing | -| monitoringConsoleRef | string | Logical name assigned to the Monitoring Console pod. You can set the name before or after the MC pod creation.| -| serviceAccount | [ServiceAccount](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) | Represents the service account used by the pods deployed by the CRD | -| extraEnv | Extra environment variables | Extra environment variables to be passed to the Splunk instance containers | -| readinessInitialDelaySeconds | readinessProbe [initialDelaySeconds](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes) | Defines `initialDelaySeconds` for Readiness probe | -| livenessInitialDelaySeconds | livenessProbe [initialDelaySeconds](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-command) | Defines `initialDelaySeconds` for the Liveness probe | -| imagePullSecrets | [imagePullSecrets](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) | Config to pull images from private registry. Use in conjunction with `image` config from [common spec](#common-spec-parameters-for-all-resources) | - -## LicenseManager Resource Spec Parameters - -```yaml -apiVersion: enterprise.splunk.com/v4 -kind: LicenseManager -metadata: - name: example -spec: - volumes: - - name: licenses - configMap: - name: splunk-licenses - licenseUrl: /mnt/licenses/enterprise.lic -``` - -Please see [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources) -and [Common Spec Parameters for All Splunk Enterprise Resources](#common-spec-parameters-for-all-splunk-enterprise-resources). -The `LicenseManager` resource does not provide any additional configuration parameters. - - -## Standalone Resource Spec Parameters - -```yaml -apiVersion: enterprise.splunk.com/v4 -kind: Standalone -metadata: - name: standalone - labels: - app: SplunkStandAlone - type: Splunk - finalizers: - - enterprise.splunk.com/delete-pvc -``` - -In addition to [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources) -and [Common Spec Parameters for All Splunk Enterprise Resources](#common-spec-parameters-for-all-splunk-enterprise-resources), -the `Standalone` resource provides the following `Spec` configuration parameters: - -| Key | Type | Description | -| ---------- | ------- | ------------------------------------------------- | -| replicas | integer | The number of standalone replicas (defaults to 1) | - - -## SearchHeadCluster Resource Spec Parameters - -```yaml -apiVersion: enterprise.splunk.com/v4 -kind: SearchHeadCluster -metadata: - name: example -spec: - replicas: 5 -``` - -In addition to [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources) -and [Common Spec Parameters for All Splunk Enterprise Resources](#common-spec-parameters-for-all-splunk-enterprise-resources), -the `SearchHeadCluster` resource provides the following `Spec` configuration parameters: - -| Key | Type | Description | -| -------- | ------- | ------------------------------------------------------------ | -| replicas | integer | The number of search heads cluster members (minimum of 3, which is the default) | - -## ClusterManager Resource Spec Parameters -ClusterManager resource does not have a required spec parameter, but to configure SmartStore, you can specify indexes and volume configuration as below - -```yaml -apiVersion: enterprise.splunk.com/v4 -kind: ClusterManager -metadata: - name: example-cm -spec: - smartstore: - defaults: - volumeName: msos_s2s3_vol - indexes: - - name: salesdata1 - remotePath: $_index_name - volumeName: msos_s2s3_vol - - name: salesdata2 - remotePath: $_index_name - volumeName: msos_s2s3_vol - - name: salesdata3 - remotePath: $_index_name - volumeName: msos_s2s3_vol - volumes: - - name: msos_s2s3_vol - path: - endpoint: - secretRef: s3-secret -``` - -## IndexerCluster Resource Spec Parameters - -```yaml -apiVersion: enterprise.splunk.com/v4 -kind: IndexerCluster -metadata: - name: example -spec: - replicas: 3 - clusterManagerRef: - name: example-cm -``` -Note: `clusterManagerRef` is required field in case of IndexerCluster resource since it will be used to connect the IndexerCluster to ClusterManager resource. - -In addition to [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources) -and [Common Spec Parameters for All Splunk Enterprise Resources](#common-spec-parameters-for-all-splunk-enterprise-resources), -the `IndexerCluster` resource provides the following `Spec` configuration parameters: - -| Key | Type | Description | -| ---------- | ------- | ----------------------------------------------------- | -| replicas | integer | The number of indexer cluster members (defaults to 1) | - - -## MonitoringConsole Resource Spec Parameters - -```yaml -cat < 2.5" +# If you want to use GitHub Pages, remove the "gem "jekyll"" above and +# uncomment the line below. To upgrade, run `bundle update github-pages`. +gem "github-pages", group: :jekyll_plugins +# If you have any plugins, put them here! +# group :jekyll_plugins do +# gem "jekyll-feed", "~> 0.12" +# gem "jekyll-external-links" +# end + +# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem +# do not have a Java counterpart. +# gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby] + +gem "webrick", "~> 1.8" +gem "just-the-docs", "~> 0.7.0" \ No newline at end of file diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock new file mode 100644 index 000000000..94f49eac3 --- /dev/null +++ b/docs/Gemfile.lock @@ -0,0 +1,284 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (6.1.7.6) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.11.1) + colorator (1.1.0) + commonmarker (0.23.10) + concurrent-ruby (1.2.3) + dnsruby (1.70.0) + simpleidn (~> 0.2.1) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + ethon (0.16.0) + ffi (>= 1.15.0) + eventmachine (1.2.7) + execjs (2.9.1) + faraday (2.0.0) + ruby2_keywords (>= 0.0.4) + ffi (1.16.3) + forwardable-extended (2.6.0) + gemoji (3.0.1) + github-pages (228) + github-pages-health-check (= 1.17.9) + jekyll (= 3.9.3) + jekyll-avatar (= 0.7.0) + jekyll-coffeescript (= 1.1.1) + jekyll-commonmark-ghpages (= 0.4.0) + jekyll-default-layout (= 0.1.4) + jekyll-feed (= 0.15.1) + jekyll-gist (= 1.5.0) + jekyll-github-metadata (= 2.13.0) + jekyll-include-cache (= 0.2.1) + jekyll-mentions (= 1.6.0) + jekyll-optional-front-matter (= 0.3.2) + jekyll-paginate (= 1.1.0) + jekyll-readme-index (= 0.3.0) + jekyll-redirect-from (= 0.16.0) + jekyll-relative-links (= 0.6.1) + jekyll-remote-theme (= 0.4.3) + jekyll-sass-converter (= 1.5.2) + jekyll-seo-tag (= 2.8.0) + jekyll-sitemap (= 1.4.0) + jekyll-swiss (= 1.0.0) + jekyll-theme-architect (= 0.2.0) + jekyll-theme-cayman (= 0.2.0) + jekyll-theme-dinky (= 0.2.0) + jekyll-theme-hacker (= 0.2.0) + jekyll-theme-leap-day (= 0.2.0) + jekyll-theme-merlot (= 0.2.0) + jekyll-theme-midnight (= 0.2.0) + jekyll-theme-minimal (= 0.2.0) + jekyll-theme-modernist (= 0.2.0) + jekyll-theme-primer (= 0.6.0) + jekyll-theme-slate (= 0.2.0) + jekyll-theme-tactile (= 0.2.0) + jekyll-theme-time-machine (= 0.2.0) + jekyll-titles-from-headings (= 0.5.3) + jemoji (= 0.12.0) + kramdown (= 2.3.2) + kramdown-parser-gfm (= 1.1.0) + liquid (= 4.0.4) + mercenary (~> 0.3) + minima (= 2.5.1) + nokogiri (>= 1.13.6, < 2.0) + rouge (= 3.26.0) + terminal-table (~> 1.4) + github-pages-health-check (1.17.9) + addressable (~> 2.3) + dnsruby (~> 1.60) + octokit (~> 4.0) + public_suffix (>= 3.0, < 5.0) + typhoeus (~> 1.3) + html-pipeline (2.14.3) + activesupport (>= 2) + nokogiri (>= 1.4) + http_parser.rb (0.8.0) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + jekyll (3.9.3) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (>= 0.7, < 2) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 2.0) + kramdown (>= 1.17, < 3) + liquid (~> 4.0) + mercenary (~> 0.3.3) + pathutil (~> 0.9) + rouge (>= 1.7, < 4) + safe_yaml (~> 1.0) + jekyll-avatar (0.7.0) + jekyll (>= 3.0, < 5.0) + jekyll-coffeescript (1.1.1) + coffee-script (~> 2.2) + coffee-script-source (~> 1.11.1) + jekyll-commonmark (1.4.0) + commonmarker (~> 0.22) + jekyll-commonmark-ghpages (0.4.0) + commonmarker (~> 0.23.7) + jekyll (~> 3.9.0) + jekyll-commonmark (~> 1.4.0) + rouge (>= 2.0, < 5.0) + jekyll-default-layout (0.1.4) + jekyll (~> 3.0) + jekyll-feed (0.15.1) + jekyll (>= 3.7, < 5.0) + jekyll-gist (1.5.0) + octokit (~> 4.2) + jekyll-github-metadata (2.13.0) + jekyll (>= 3.4, < 5.0) + octokit (~> 4.0, != 4.4.0) + jekyll-include-cache (0.2.1) + jekyll (>= 3.7, < 5.0) + jekyll-mentions (1.6.0) + html-pipeline (~> 2.3) + jekyll (>= 3.7, < 5.0) + jekyll-optional-front-matter (0.3.2) + jekyll (>= 3.0, < 5.0) + jekyll-paginate (1.1.0) + jekyll-readme-index (0.3.0) + jekyll (>= 3.0, < 5.0) + jekyll-redirect-from (0.16.0) + jekyll (>= 3.3, < 5.0) + jekyll-relative-links (0.6.1) + jekyll (>= 3.3, < 5.0) + jekyll-remote-theme (0.4.3) + addressable (~> 2.0) + jekyll (>= 3.5, < 5.0) + jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) + rubyzip (>= 1.3.0, < 3.0) + jekyll-sass-converter (1.5.2) + sass (~> 3.4) + jekyll-seo-tag (2.8.0) + jekyll (>= 3.8, < 5.0) + jekyll-sitemap (1.4.0) + jekyll (>= 3.7, < 5.0) + jekyll-swiss (1.0.0) + jekyll-theme-architect (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-cayman (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-dinky (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-hacker (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-leap-day (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-merlot (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-midnight (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-minimal (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-modernist (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-primer (0.6.0) + jekyll (> 3.5, < 5.0) + jekyll-github-metadata (~> 2.9) + jekyll-seo-tag (~> 2.0) + jekyll-theme-slate (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-tactile (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-time-machine (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-titles-from-headings (0.5.3) + jekyll (>= 3.3, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + jemoji (0.12.0) + gemoji (~> 3.0) + html-pipeline (~> 2.2) + jekyll (>= 3.0, < 5.0) + just-the-docs (0.7.0) + jekyll (>= 3.8.5) + jekyll-include-cache + jekyll-seo-tag (>= 2.0) + rake (>= 12.3.1) + kramdown (2.3.2) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.8.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.3.6) + mini_portile2 (2.8.5) + minima (2.5.1) + jekyll (>= 3.5, < 5.0) + jekyll-feed (~> 0.9) + jekyll-seo-tag (~> 2.1) + minitest (5.22.2) + nokogiri (1.13.10) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) + nokogiri (1.13.10-aarch64-linux) + racc (~> 1.4) + nokogiri (1.13.10-arm64-darwin) + racc (~> 1.4) + nokogiri (1.13.10-x86-linux) + racc (~> 1.4) + nokogiri (1.13.10-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.13.10-x86_64-linux) + racc (~> 1.4) + octokit (4.25.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (4.0.7) + racc (1.7.3) + rake (13.1.0) + rb-fsevent (0.11.2) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.6) + rouge (3.26.0) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + safe_yaml (1.0.5) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) + simpleidn (0.2.1) + unf (~> 0.1.4) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + typhoeus (1.4.1) + ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.9.1) + unicode-display_width (1.8.0) + webrick (1.8.1) + zeitwerk (2.6.13) + +PLATFORMS + aarch64-linux + arm-linux + arm64-darwin + x86-linux + x86_64-darwin + x86_64-linux + +DEPENDENCIES + github-pages + just-the-docs (~> 0.7.0) + webrick (~> 1.8) + +BUNDLED WITH + 2.4.22 diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index dc10853ae..000000000 --- a/docs/README.md +++ /dev/null @@ -1,199 +0,0 @@ -# Getting Started with the Splunk Operator for Kubernetes - -The Splunk Operator for Kubernetes enables you to quickly and easily deploy Splunk Enterprise on your choice of private or public cloud provider. The Operator simplifies scaling and management of Splunk Enterprise by automating administrative workflows using Kubernetes best practices. - -The Splunk Operator runs as a container, and uses the Kubernetes [operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) and [custom resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) objects to create and manage a scalable and sustainable Splunk Enterprise environment. - -This guide is intended to help new users get up and running with the -Splunk Operator for Kubernetes. It is divided into the following sections: - -* [Known Issues for the Splunk Operator](#known-issues-for-the-splunk-operator) -* [Prerequisites for the Splunk Operator](#prerequisites-for-the-splunk-operator) -* [Installing the Splunk Operator](#installing-the-splunk-operator) -* [Creating Splunk Enterprise Deployments](#creating-a-splunk-enterprise-deployment) -* [Securing Splunk Deployments in Kubernetes](Security.md) -* [Contacting Support](#contacting-support) - -## Support Resources - -SPLUNK SUPPORTED: The Splunk Operator for Kubernetes is a supported method for deploying distributed Splunk Enterprise environments using containers. The Splunk Operator is categorized as an Extension and subject to the support terms found [here](https://www.splunk.com/en_us/legal/splunk-software-support-policy.html). Splunk Enterprise deployed using the Splunk Operator is subject to the applicable support level offered [here](https://www.splunk.com/en_us/customer-success/support-programs.html). - -COMMUNITY DEVELOPED: Splunk Operator for Kubernetes is an open source product developed by Splunkers with contributions from the community of partners and customers. The primary reason why Splunk is taking this approach is to push product development closer to those that use and depend upon it. This direct connection will help us all be more successful and move at a rapid pace. - -If you're interested in contributing to the SOK open source project, review the [Contributing to the Project](CONTRIBUTING.md) page. - -**Community Support & Discussions on -[Slack](https://splunk-usergroups.slack.com)** channel #splunk-operator-for-kubernetes - -**File Issues or Enhancements in -[GitHub](https://github.com/splunk/splunk-operator/issues)** splunk/splunk-operator - - -## Known Issues for the Splunk Operator - -Review the [Change Log](ChangeLog.md) page for a history of changes in each release. - -## Prerequisites for the Splunk Operator - -Please check [release notes](https://github.com/splunk/splunk-operator/releases) for supportability matrix - -## Platform recommendations - - -The Splunk Operator should work with any [CNCF certified distribution](https://www.cncf.io/certification/software-conformance/) of Kubernetes. We do not have platform recommendations, but this is a table of platforms that our developers, customers, and partners have used successfully with the Splunk Operator. - - - - - - -
Splunk Development & Testing Platforms Amazon Elastic Kubernetes Service (EKS), Google Kubernetes Engine (GKE)
Customer Reported Platforms Microsoft Azure Kubernetes Service (AKS), Red Hat OpenShift
Partner Tested Platforms HPE Ezmeral
Other Platforms CNCF certified distribution
- -### Splunk Enterprise Compatibility - -Each Splunk Operator release has specific Splunk Enterprise compatibility requirements. Splunk Operator can support more than one version of Splunk Enterprise release. Before installing or upgrading the Splunk Operator, review the [release notes](https://github.com/splunk/splunk-operator/releases) to verify version compatibility with Splunk Enterprise releases. - -Each release of splunk-operator is preset to latest release mentioned in [release notes](https://github.com/splunk/splunk-operator/releases), if user wants to change that to any release version specified in [release notes](https://github.com/splunk/splunk-operator/releases), they can simply change envionment variable `RELATED_IMAGE_SPLUNK_ENTERPRISE` in splunk-operator deployment manifest file. - - -### Splunk Apps Installation - -Apps and add-ons can be installed using the Splunk Operator by following the instructions given at [Installing Splunk Apps](Examples.md#installing-splunk-apps). For the installation of premium apps please refer to [Premium Apps Installation Guide](PremiumApps.md). - -### Docker requirements -The Splunk Operator requires these docker images to be present or available to your Kubernetes cluster: - -* `splunk/splunk-operator`: The Splunk Operator image built by this repository or the [official release](https://hub.docker.com/r/splunk/splunk-operator) -* `splunk/splunk:`: The [Splunk Enterprise image](https://github.com/splunk/docker-splunk) - - -All of the Splunk Enterprise images are publicly available on [Docker Hub](https://hub.docker.com/). If your cluster does not have access to pull from Docker Hub, see the [Required Images Documentation](Images.md) page. - -Review the [Change Log](ChangeLog.md) page for a history of changes and Splunk Enterprise compatibility for each release. - -### Hardware Resources Requirements -The resource guidelines for running production Splunk Enterprise instances in pods through the Splunk Operator are the same as running Splunk Enterprise natively on a supported operating system and file system. Refer to the Splunk Enterprise [Reference Hardware documentation](https://docs.splunk.com/Documentation/Splunk/latest/Capacity/Referencehardware) for additional details. We would also recommend following the same guidance on [Splunk Enterprise for disabling Transparent Huge Pages (THP)](https://docs.splunk.com/Documentation/Splunk/latest/ReleaseNotes/SplunkandTHP) for the nodes in your Kubernetes cluster. Please be aware that this may impact performance of other non-Splunk workloads. - -#### Minimum Reference Hardware -Based on Splunk Enterprise [Reference Hardware documentation](https://docs.splunk.com/Documentation/Splunk/latest/Capacity/Referencehardware), a summary of the minimum reference hardware requirements is given below. - -| Standalone | Search Head / Search Head Cluster | Indexer Cluster | -| ---------- | ------- | ------- | -| _Each Standalone Pod: 12 Physical CPU Cores or 24 vCPU at 2Ghz or greater per core, 12GB RAM._| _Each Search Head Pod: 16 Physical CPU Cores or 32 vCPU at 2Ghz or greater per core, 12GB RAM._| _Each Indexer Pod: 12 Physical CPU cores, or 24 vCPU at 2GHz or greater per core, 12GB RAM._ | - - -#### _Using Kubernetes Quality of Service Classes_ - -In addition to the guidelines provided in the reference hardware, [Kubernetes Quality of Service Classes](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/) can be used to configure CPU/Mem resources allocations that map to your _service level objectives_. For further information on utilizing Kubernetes Quality of Service (QoS) classes, see the table below: - - -| QoS | Summary| Description | -| ---------- | ------- | ------- | -| _Guaranteed_ | _CPU/Mem ```requests``` = CPU/Mem ```limits```_ | _When the CPU and memory ```requests``` and ```limits``` values are equal, the pod is given a QoS class of Guaranteed. This level of service is recommended for Splunk Enterprise ___production environments___._ | -| _Burstable_ | _CPU/Mem ```requests``` < CPU/Mem ```limits```_ | _When the CPU and memory ```requests``` value is set lower than the ```limits``` the pod is given a QoS class of Burstable. This level of service is useful in a user acceptance testing ___(UAT) environment___, where the pods run with minimum resources, and Kubernetes allocates additional resources depending on usage._| -| _BestEffort_ | _No CPU/Mem ```requests``` or ```limits``` are set_ | _When the ```requests``` or ```limits``` values are not set, the pod is given a QoS class of BestEffort. This level of service is sufficient for ___testing, or a small development task___._ | - -Examples on how to implement these QoS are given at [Examples of Guaranteed and Burstable QoS](CustomResources.md#examples-of-guaranteed-and-burstable-qos) section. - - -### Storage guidelines -The Splunk Operator uses Kubernetes [Persistent Volume Claims](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) to store all of your Splunk Enterprise configuration ("$SPLUNK_HOME/etc" path) and event ("$SPLUNK_HOME/var" path) data. If one of the underlying machines fail, Kubernetes will automatically try to recover by restarting the Splunk Enterprise pods on another machine that is able to reuse the same data volumes. This minimizes the maintenance burden on your operations team by reducing the impact of common hardware failures to the equivalent of a service restart. -The use of Persistent Volume Claims requires that your cluster is configured to support one or more Kubernetes persistent [Storage Classes](https://kubernetes.io/docs/concepts/storage/storage-classes/). See the [Setting Up a Persistent Storage for Splunk](StorageClass.md) page for more -information. - -### What Storage Type To Use? - -The Kubernetes infrastructure must have access to storage that meets or exceeds the recommendations provided in the Splunk Enterprise storage type recommendations at [Reference Hardware documentation - what storage type to use for a given role?](https://docs.splunk.com/Documentation/Splunk/latest/Capacity/Referencehardware#What_storage_type_should_I_use_for_a_role.3F) In summary, Indexers with SmartStore need NVMe or SSD storage to provide the necessary IOPs for a successful Splunk Enterprise environment. - - -### Splunk SmartStore Required -For production environments, we are requiring the use of Splunk SmartStore. As a Splunk Enterprise deployment's data volume increases, demand for storage typically outpaces demand for compute resources. [Splunk's SmartStore Feature](https://docs.splunk.com/Documentation/Splunk/latest/Indexer/AboutSmartStore) allows you to manage your indexer storage and compute resources in a ___cost-effective___ manner by scaling those resources separately. SmartStore utilizes a fast storage cache on each indexer node to keep recent data locally available for search and keep other data in a remote object store. Look into the [SmartStore Resource Guide](SmartStore.md) document for configuring and using SmartStore through operator. - -## Installing the Splunk Operator - -A Kubernetes cluster administrator can install and start the Splunk Operator for specific namespace by running: -``` -kubectl apply -f https://github.com/splunk/splunk-operator/releases/download/2.4.0/splunk-operator-namespace.yaml --server-side --force-conflicts -``` - -A Kubernetes cluster administrator can install and start the Splunk Operator for cluster-wide by running: -``` -kubectl apply -f https://github.com/splunk/splunk-operator/releases/download/2.4.0/splunk-operator-cluster.yaml --server-side --force-conflicts -``` - -The [Advanced Installation Instructions](Install.md) page offers guidance for advanced configurations, including the use of private image registries, installation at cluster scope, and installing the Splunk Operator as a user who is not a Kubernetes administrator. Users of Red Hat OpenShift should review the [Red Hat OpenShift](OpenShift.md) page. - -*Note: We recommended that the Splunk Enterprise Docker image is copied to a private registry, or directly onto your Kubernetes workers before creating large Splunk Enterprise deployments. See the [Required Images Documentation](Images.md) page, and the [Advanced Installation Instructions](Install.md) page for guidance on working with copies of the Docker images.* - -After the Splunk Operator starts, you'll see a single pod running within your current namespace: -``` -$ kubectl get pods -NAME READY STATUS RESTARTS AGE -splunk-operator-75f5d4d85b-8pshn 1/1 Running 0 5s -``` - -### Installation using Helm charts - -Installing the Splunk Operator using Helm allows you to quickly deploy the operator and Splunk Enterprise in a Kubernetes cluster. The operator and custom resources are easily configurable allowing for advanced installations including support for Splunk Validated Architectures. Helm also provides a number of features to manage the operator and custom resource lifecycle. The [Installation using Helm](Helm.md) page will walk you through installing and configuring Splunk Enterprise deployments using Helm charts. - -## Upgrading the Splunk Operator - -For information on upgrading the Splunk Operator, see the [How to upgrade Splunk Operator and Splunk Enterprise Deployments](SplunkOperatorUpgrade.md) page. - -## Creating a Splunk Enterprise deployment - -The `Standalone` custom resource is used to create a single instance deployment of Splunk Enterprise. For example: - -1. Run the command to create a deployment named “s1”: - - -```yaml -cat <- + The Splunk Operator for Kubernetes (SOK) makes it easy for Splunk Administrators to deploy and operate Enterprise deployments in a Kubernetes infrastructure. + + Packaged as a container, it uses the operator pattern to manage Splunk-specific custom resources, following best practices to manage all the underlying Kubernetes objects for you. +github_username: splunk +domain: splunk.github.io +url: "https://splunk.github.io" +favicon_ico: /assets/images/favicon.ico +aux_links: + "Splunk Operator for Kubernetes on GitHub": + - "//github.com/splunk/splunk-operator" + +# Build settings +theme: just-the-docs +plugins: + - jekyll-external-links + # - jekyll-feed + +krmadown: + toc_levels: [1, 2, 3] + +collections: + helm: + permalink: "/:path/" + output: true + installation: + permalink: "/:collection/:path" + output: true + configuration: + permalink: "/:collection/:path" + output: true + troubleshooting: + permalink: "/:collection/:path" + output: true + +just_the_docs: + collections: + installation: + name: Installation + nav_fold: true + configuration: + name: Configuration + nav_fold: true + troubleshooting: + name: Troubleshooting + nav_fold: true + +# The colors grey-lt, grey-dk, purple, +# blue, green, yellow, and red are predefined +callouts: + note: + title: Note + color: blue + highlight: + color: yellow + +defaults: + - + scope: + path: "" + values: + splunk_operator_version: "2.5.0" + splunk_enterprise_version: "9.1.3" + - + scope: + path: "" + type: "pages" + values: + nav_after_collections: false + - + scope: + path: "" + type: "installation" + values: + layout: "default" + - + scope: + path: "" + type: "configuration" + values: + layout: "default" + - + scope: + path: "" + type: "troubleshooting" + values: + layout: "default" \ No newline at end of file diff --git a/docs/AppFramework.md b/docs/_configuration/AppFramework.md similarity index 63% rename from docs/AppFramework.md rename to docs/_configuration/AppFramework.md index 4a9eaa828..bc505cb47 100644 --- a/docs/AppFramework.md +++ b/docs/_configuration/AppFramework.md @@ -1,38 +1,294 @@ +--- +title: App Framework +nav_order: 21 +layout: "default" +--- + # App Framework Resource Guide +{: .no_toc } +The Splunk Operator provides support for Splunk App and Add-On installation and upgrades using the App Framework. The App Framework supports configuration management of Splunk Enterprise Cluster and Standalone deployments, this simplifies the managemnt of complex Splunk environments by automating the app install process for Clustered Indexers, Clustered Search Heads and all Splunk standalone instances. + +The App Framework specification supports configuration management using the Splunk Enterprise `ClusterManager`, `SearchHeadCluster`, `Standalone`, `LicenceManager`, and `MonitoringConsole` Custom Resources. For more information about the configuration paramaters avaliable, refer to the [Custom Resource Reference](/configuration/CustomResources#app-framework-resource-spec-parameters). + + +#### Table of contents +{: .no_toc } +- TOC +{:toc} -The Splunk Operator provides support for Splunk app and add-on deployment using the App Framework. The App Framework specification supports configuration management using the Splunk Enterprise cluster and standalone [custom resources](https://splunk.github.io/splunk-operator/CustomResources.html) (CR). ## Prerequisites -Utilizing the App Framework requires one of the following remote storage providers: - * An Amazon S3 or S3-API-compliant remote object storage location - * Azure blob storage +- Amazon S3 or S3-API-compliant remote object storage OR Azure blob storage. +- The App framework requires read-only access to the path used to host the apps. DO NOT give any other access to the operator to maintain the integrity of data in S3 bucket or Azure blob container. +- Splunk apps and add-ons in a .tgz or .spl archive format. +- Connections to the remote object storage endpoint need to be secured using a minimum version of TLS 1.2. +- A persistent storage volume and path for the Operator Pod. See [Add a persistent storage volume to the Operator pod](#add-a-persistent-storage-volume-to-the-operator-pod). -### Prerequisites common to both remote storage providers -* The App framework requires read-only access to the path used to host the apps. DO NOT give any other access to the operator to maintain the integrity of data in S3 bucket or Azure blob container. -* Splunk apps and add-ons in a .tgz or .spl archive format. -* Connections to the remote object storage endpoint need to be secured using a minimum version of TLS 1.2. -* A persistent storage volume and path for the Operator Pod. See [Add a persistent storage volume to the Operator pod](#add-a-persistent-storage-volume-to-the-operator-pod). ### Prerequisites for S3 based remote object storage -* Create role and role-binding for splunk-operator service account, to provide read-only access for S3 credentials. -* The remote object storage credentials provided as a kubernetes secret, or in an IAM role. -* If you are using [interface VPC endpoints](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html) with DNS enabled to access AWS S3, please update the corresponding volume endpoint URL with one of the `DNS names` from the endpoint. Please ensure that the endpoint has access to the S3 buckets using the credentials configured. Similarly other endpoint URLs with access to the S3 buckets can also be used. + +- The remote object storage credentials provided as a kubernetes secret, or in an IAM role. +- Create role and role-binding for splunk-operator service account to provide read-only access for the kubernetes secret that contains your S3 credentials. + [Kubernetes Docs - RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole) +- If you are using [Interface VPC endpoints](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html) with DNS enabled to access AWS S3, please update the corresponding volume endpoint URL with one of the `DNS names` from the endpoint. + ### Prerequisites for Azure Blob remote object storage -* The remote object storage credentials provided as a kubernetes secret. -* OR, Use "Managed Indentity" role assigment to the Azure blob container. See [Setup Azure bob access with Managed Indentity](#setup-azure-bob-access-with-managed-indentity) -Splunk apps and add-ons deployed or installed outside of the App Framework are not managed, and are unsupported. +- The remote object storage credentials provided as a kubernetes secret. +- OR, Use "Managed Indentity" role assigment to the Azure blob container. See [Setup Azure bob access with Managed Indentity](#setup-azure-bob-access-with-managed-indentity) + +{: .note } +For the App Framework to detect that an app or add-on had changed, the updated app must use the same archive file name as the previously deployed one. +Splunk apps and add-ons deployed or installed outside of the App Framework are not managed by the Splunk Operator. + + +## Add a persistent storage volume to the Operator pod + +If the persistent storage volume is not configured for the Operator, by default, the App Framework uses the main memory (RAM) as the staging area for app package downloads. In order to avoid pressure on the main memory, it is strongly advised to use a persistent volume for the operator pod. + + +{:style="counter-reset:step-counter"} +1. Create the persistent volume used by the Operator pod to cache apps and add-ons + + ```yaml + kind: PersistentVolumeClaim + apiVersion: v1 + metadata: + name: "operator-volume-claim" + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 8Gi + storageClassName: gp2 + ``` + +{:style="counter-reset:none"} +2. Associate the persistent volume with the Operator pod by updating the Operator configuration + + ```yaml + volumes: + - name: app-staging + persistentVolumeClaim: + claimName: "operator-volume-claim" + ``` + +{:style="counter-reset:none"} +3. Mount the volume on the path + + ```yaml + volumeMounts: + - mountPath: /opt/splunk/appframework/ + name: app-staging + ``` + + +A full example of the Operator configuration: +```yaml +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: operator-volume-claim +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 8Gi + storageClassName: gp2 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: splunk-operator +spec: + replicas: 1 + selector: + matchLabels: + name: splunk-operator + template: + metadata: + labels: + name: splunk-operator + spec: + securityContext: + fsGroup: 1001 + serviceAccountName: splunk-operator + containers: + - name: splunk-operator + image: "docker.io/splunk/splunk-operator:{{ page.splunk_operator_version }}" + volumeMounts: + - mountPath: /opt/splunk/appframework/ + name: app-staging + imagePullPolicy: IfNotPresent + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: "splunk-operator" + - name: RELATED_IMAGE_SPLUNK_ENTERPRISE + value: "docker.io/splunk/splunk:{{ page.splunk_enterprise_version }}" + volumes: + - name: app-staging + persistentVolumeClaim: + claimName: operator-volume-claim +``` + + +## Trigger Manual initiation of managed apps + +You can prevent the App Framework from automatically polling the remote storage for app changes. By configuring the `appsRepoPollIntervalSeconds` setting to `0`, the App Framework polling is disabled, and the configMap is updated with a new `status` field. The App Framework will perform an initial poll of the remote storage, even when the CR is initialized with polling disabled. + +When you're ready to initiate an app check using the App Framework, manually update the `status` field in the configMap for that Custom Resource type to `on`. The 'status' field defaults to 'off'. + +For example, you deployed one Standalone CR with app framework enabled and the `appsRepoPollIntervalSeconds` set to `0`. + +```bash +kubectl get standalone +``` + +As mentioned above, Splunk Operator will create the configMap (assuming `default` namespace) `splunk-default-manual-app-update` with an entry for Standalone CR as below: + +```yaml +apiVersion: v1 +data: + Standalone: |- + status: off + refCount: 1 +kind: ConfigMap +metadata: + creationTimestamp: "2021-08-24T01:04:01Z" + name: splunk-manual-app-update + namespace: default + ownerReferences: + - apiVersion: enterprise.splunk.com/v3 + controller: false + kind: Standalone + name: s1 + uid: ddb9528f-2e25-49be-acd4-4fadde489849 + resourceVersion: "75406013" + selfLink: /api/v1/namespaces/default/configmaps/splunk-manual-app-update + uid: 413c6053-af4f-4cb3-97e0-6dbe7cd17721 +``` + +To trigger manual checking of apps, update the configMap, and set the `status` field to `on` for the Standalone CR as below: + +```bash +kubectl patch cm/splunk-default-manual-app-update --type merge -p '{"data":{"Standalone":"status: on\nrefCount: 1"}}' +``` + +The App Framework will perform its checks, update or install apps, and reset the `status` to `off` when it has completed its tasks. + +To reinstate automatic polling, update the CR `appsRepoPollIntervalSeconds` setting to a value greater than `0`. + +{: .note } +All CRs of the same type must have polling enabled, or disabled. For example, if `appsRepoPollIntervalSeconds` is set to '0' for one Standalone CR, all other Standalone CRs must also have polling disabled. Use the `kubectl` command to identify all CRs of the same type before updating the polling interval. You can experience unexpected polling behavior if there are CRs configured with a mix of polling enabled and disabled. + + +## App Framework Limitations + +The App Framework does not preview, analyze, verify versions, or enable Splunk Apps and Add-ons. The administrator is responsible for previewing the app or add-on contents, verifying the app is enabled, and that the app is supported with the version of Splunk Enterprise deployed in the containers. For Splunk app packaging specifications see [Package apps for Splunk Cloud or Splunk Enterprise](https://dev.splunk.com/enterprise/docs/releaseapps/packageapps/) in the Splunk Enterprise Developer documentation. The app archive files must end with .spl or .tgz; all other files are ignored. + +1. The App Framework has no support to remove an app or add-on once it’s been deployed. To disable an app, update the archive contents located in the App Source, and set the app.conf state to disabled. + +2. The App Framework defines one worker per CR type. For example, if you have multiple clusters receiveing app updates, a delay while managing one cluster will delay the app updates to the other cluster. + + +## Setup Azure blob access with Managed Indentity + +Azure Managed identities can be used to provide IAM access to the blobs. With managed identities, the AKS nodes, that host the pods, can retrieve a OAuth token that provides authorization for the Splunk operator pod to read the app packages stored in the Azure Storage account. The key point here is that the AKS node is associated with a Managed Identity and this managed identity is given a `role` for read access called `Storage Blob Data Reader` to the azure storage account. + +Here are the steps showing an example of assiging managed identity: + +Familiarize yourself with [AKS managed identity concepts](https://learn.microsoft.com/en-us/azure/aks/use-managed-identity) + +The names used below, such as resource-group name and AKS cluster name, are for examples purpose, please change them to the values as per your setup. + +These steps cover creating resource group and AKS cluster also but you can skip them if you already have them created. + +1. Create an Azure resource group +```bash +az group create --name splunkOperatorResourceGroup --location westus2 +``` + +2. Create AKS Cluster +```bash +az aks create -g splunkOperatorResourceGroup -n splunkOperatorCluster --enable-managed-identity +``` + +3. Get credentials to access cluster +```bash +az aks get-credentials --resource-group splunkOperatorResourceGroup --name splunkOperatorCluster +``` + +4. Get the Kubelet user managed identity +```bash +az identity list +``` + +Find the object that has -agentpool in the name field eg. `"name": "splunkOperatorCluster-agentpool"` + + ```json + { + "clientId": "a5890776-24e6-4f5b-9b6c-**************", + "id": "/subscriptions/f428689e-c379-4712--**************/resourcegroups/MC_splunkOperatorResourceGroup_splunkOperatorCluster_westus2/providers/Microsoft.ManagedIdentity/userAssignedIdentities/splunkOperatorCluster-agentpool", + "location": "westus2", + "name": "splunkOperatorCluster-agentpool", + "principalId": "f0f04120-6a36-49bc--**************", + "resourceGroup": "MC_splunkOperatorResourceGroup_splunkOperatorCluster_westus2", + "tags": {}, + "tenantId": "8add7810-b62a--**************", + "type": "Microsoft.ManagedIdentity/userAssignedIdentities" + } + ``` + + Extract the principalId value from the outout above. Or you can use the following command to get the principalId + ```bash + AZ_PRINCIPAL_ID=$(az identity show --name --resource-group "" --query 'principalId' --output tsv) + ``` + + Example: + ```bash + AZ_PRINCIPAL_ID=$(az identity show --name splunkOperatorCluster-agentpool --resource-group "MC_splunkOperatorResourceGroup_splunkOperatorCluster_westus2" --query 'principalId' --output tsv) + echo $AZ_PRINCIPAL_ID + ``` + +5. Assign read access for Kubelet user managed identity to the storage account + +Use the `principalId` from the above section and assign it to the storage account +```bash +az role assignment create --assignee $AZ_PRINCIPAL_ID --role 'Storage Blob Data Reader' --scope /subscriptions//resourceGroups//providers/Microsoft.Storage/storageAccounts/ +``` + +For this example, if is splunkOperatorResourceGroup and is mystorageaccount then the command would be: +```bash +az role assignment create --assignee "f0f04120-6a36-49bc--**************" --role 'Storage Blob Data Reader' --scope /subscriptions/f428689e-c379-4712--**************/resourceGroups/splunkOperatorResourceGroup/providers/Microsoft.Storage/storageAccounts/mystorageaccount +``` + +After this, you can use App framework for Azure blob without secrets. + +### Azure Blob Authorization Recommendations + +Azure allows "Managed Identities" assignment at the "storage accounts" level as well as at specific buckets levels. A managed identity that is assigned read permissions at a storage account level will have read access for all the buckets within that storage account. As a good security practice, you should assign the managed identity to only the specific buckets and not to the whole storage account. + +In contrast to "Managed Identities", Azure allows the "shared access keys" configurable only at the storage accounts level. When using the "secretRef" configuration in the CRD, the underlying secret key will allow both read and write access to the storage account (and all the buckets within it). So, based on your security needs, you may want to consider using "Managed Identities" instead of secrets. Also note that there isn't an automated way of rotating the secret key, so in case you are using these keys, please rotate them at regular intervals of times such as 90 days interval. -Note: For the App Framework to detect that an app or add-on had changed, the updated app must use the same archive file name as the previously deployed one. ## Examples of App Framework usage -Following section shows examples of using App Framework for both remote data storages. First, the examples for S3 based remote object storage are given and then same examples are covered for Azure blob. The examples in both the cases have lot of commonalities and the places they differ are mainly in the values for `storageType`, `provider` and `endpoint`. There are also some differences in the authoriziation setup for using IAM /Managed Identity in both remote data storages. -### Examples of App Framework usage +Following section shows examples of using App Framework for both remote data storages. First, the examples for S3 based remote object storage are given and then same examples are covered for Azure blob. The examples in both the cases have lot of commonalities and the places they differ are mainly in the values for `storageType`, `provider` and `endpoint`. There are also some differences in the authoriziation setup for using IAM/Managed Identity in both remote data storages. + -#### How to use the App Framework on a Standalone CR +### How to use the App Framework on a Standalone CR In this example, you'll deploy a Standalone CR with a remote storage volume, the location of the app archive, and set the installation location for the Splunk Enterprise Pod instance by using `scope`. @@ -128,7 +384,7 @@ By default, the App Framework polls the remote object storage location for new o For more information, see the [Description of App Framework Specification fields](#description-of-app-framework-specification-fields). -#### How to use the App Framework on Indexer Cluster +### How to use the App Framework on Indexer Cluster This example describes the installation of apps on an Indexer Cluster and Cluster Manager. This is achieved by deploying a ClusterManager CR with a remote storage volume, setting the location of the app archives, and the installation scope to support both local and cluster app path distribution. @@ -189,7 +445,6 @@ spec: ``` Example using Azure Blob: ClusterManager.yaml - ```yaml apiVersion: enterprise.splunk.com/v4 kind: ClusterManager @@ -225,7 +480,8 @@ The App Framework detects the Splunk app or add-on archive files available in th The apps in the `networkApps` and `clusterBase` folders are deployed to the cluster manager for use on the cluster peers. The cluster manager is responsible for deploying those apps to the cluster peers. -Note: The Splunk cluster peer restarts are triggered by the contents of the Splunk apps deployed, and are not initiated by the App Framework. +{: .note } +The Splunk cluster peer restarts are triggered by the contents of the Splunk apps deployed, and are not initiated by the App Framework. The App Framework maintains a checksum for each app or add-on archive file in the App Source location. The app name and checksum is recorded in the CR, and used to compare the deployed apps to the app archive files in the App Source location. The App Framework will scan for changes to the App Source folders using the polling interval, and deploy any updated apps to the instance. For the App Framework to detect that an app or add-on had changed, the updated app must use the same archive file name as the previously deployed one. @@ -233,7 +489,8 @@ By default, the App Framework polls the remote object storage location for new o For more information, see the [Description of App Framework Specification fields](#description-of-app-framework-specification-fields) -#### How to use the App Framework on Search Head Cluster + +### How to use the App Framework on Search Head Cluster This example describes the installation of apps on the Deployer and the Search Head Cluster. This is achieved by deploying a SearchHeadCluster CR with a storage volume, the location of the app archives, and set the installation scope to support both local and cluster app distribution. @@ -334,376 +591,8 @@ The App Framework detects the Splunk app or add-on archive files available in th The apps in the `searchApps` and `machineLearningApps` folders are deployed to the Deployer for use on the clustered search heads. The Deployer is responsible for deploying those apps to the search heads. -Note: The Splunk search head restarts are triggered by the contents of the Splunk apps deployed, and are not initiated by the App Framework. +{: .note } +The Splunk search head restarts are triggered by the contents of the Splunk apps deployed, and are not initiated by the App Framework. The App Framework maintains a checksum for each app or add-on archive file in the App Source location. The app name and checksum is recorded in the CR, and used to compare the deployed apps to the app archive files in the App Source location. The App Framework will scan for changes to the App Source folders using the polling interval, and deploy any updated apps to the instance. For the App Framework to detect that an app or add-on had changed, the updated app must use the same archive file name as the previously deployed one. -By default, the App Framework polls the remote object storage location for new or changed apps at the `appsRepoPollIntervalSeconds` interval. To disable the interval check, and manage app updates manually, see the [Manual initiation of app management](#manual-initiation-of-app-management). - -For more information, see the [Description of App Framework Specification fields](#description-of-app-framework-specification-fields). - -## Description of App Framework Specification fields -The App Framework configuration is supported on the following Custom Resources: Standalone, ClusterManager, SearchHeadCluster, MonitoringConsole and LicenseManager. Configuring the App framework requires: - -* Remote Source of Apps: Define the remote storage location, including unique folders, and the path to each folder. -* Destination of Apps: Define which Custom Resources need to be configured. -* Scope of Apps: Define if the apps need to be installed and run locally (such as Standalone, Monitoring Console and License Manager,) or cluster-wide (such as Indexer Cluster, and Search Head Cluster.) - -Here is a typical App framework configuration in a Custom Resource definition: - -```yaml - appRepo: - description: Splunk Enterprise App repository. Specifies remote App - location and scope for Splunk App management - properties: - appSources: - description: List of App sources on remote storage - items: - description: AppSourceSpec defines list of App package (*.spl, - *.tgz) locations on remote volumes - properties: - location: - description: Location relative to the volume path - type: string - name: - description: Logical name for the set of apps placed in - this location. Logical name must be unique to the appRepo - type: string - scope: - description: 'Scope of the App deployment: cluster, local. - Scope determines whether the App(s) is/are installed locally - or cluster-wide' - type: string - volumeName: - description: Remote Storage Volume name - type: string - type: object - type: array - appsRepoPollIntervalSeconds: - description: Interval in seconds to check the Remote Storage for - App changes - type: integer - defaults: - description: Defines the default configuration settings for App - sources - properties: - scope: - description: 'Scope of the App deployment: cluster, local. - Scope determines whether the App(s) is/are installed locally - or cluster-wide' - type: string - volumeName: - description: Remote Storage Volume name - type: string - type: object - volumes: - description: List of remote storage volumes - items: - description: VolumeSpec defines remote volume config - properties: - endpoint: - description: Remote volume URI - type: string - name: - description: Remote volume name - type: string - path: - description: Remote volume path - type: string - provider: - description: App Package Remote Store provider. Currently supported proiders are aws, minio and azure - type: string - region: - description: Region of the remote storage volume where apps - reside. Not required for azure. - type: string - secretRef: - description: Secret object name - type: string - storageType: - description: Remote Storage type. Possible values are s3 (works with aws and minio) or blob (works with azure) - type: string - type: object - type: array - type: object -``` - -### appRepo - -`appRepo` is the start of the App Framework specification, and contains all the configurations required for App Framework to be successfully configured. - -### volumes - -`volumes` defines the remote storage configurations. The App Framework expects any apps to be installed in various Splunk deployments to be hosted in one or more remote storage volumes. - -* `name` uniquely identifies the remote storage volume name within a CR. This is used by the Operator to identify the local volume. -* `storageType` describes the type of remote storage. Currently, `s3`, `blob` are the supported storage type. -* `provider` describes the remote storage provider. Currently, `aws`, `minio` and `azure` are the supported providers. Use `s3` with `aws` or `minio` and use `blob` with `azure`. -* `endpoint` describes the URI/URL of the remote storage endpoint that hosts the apps. -* `secretRef` refers to the K8s secret object containing the static remote storage access key. This parameter is not required if using IAM role based credentials. -* `path` describes the path (including the folder) of one or more app sources on the remote store. - -### appSources - -`appSources` defines the name and scope of the appSource, the remote storage volume, and its location. - -* `name` uniquely identifies the App source configuration within a CR. This used locally by the Operator to identify the App source. -* `scope` defines the scope of the app to be installed. - * If the scope is `local`, the apps will be installed and run locally on the pod referred to by the CR. - * If the scope is `cluster`, the apps will be placed onto the configuration management node (Deployer, Cluster Manager) for deployment across the cluster referred to by the CR. - * The cluster scope is only supported on CRs that manage cluster-wide app deployment. - - | CRD Type | Scope support | App Framework support | - | :---------------- | :------------------------------------- | :-------------------- | - | ClusterManager | cluster, local | Yes | - | SearchHeadCluster | cluster, local | Yes | - | Standalone | local | Yes | - | LicenceManager | local | Yes | - | MonitoringConsole | local | Yes | - | IndexerCluster | N/A | No | - -* `volume` refers to the remote storage volume name configured under the `volumes` stanza (see previous section.) -* `location` helps configure the specific appSource present under the `path` within the `volume`, containing the apps to be installed. - -### appsRepoPollIntervalSeconds - -If app framework is enabled, the Splunk Operator creates a namespace scoped configMap named **splunk-\-manual-app-update**, which is used to manually trigger the app updates. The App Framework uses the polling interval `appsRepoPollIntervalSeconds` to check for additional apps, or modified apps on the remote object storage. - -When `appsRepoPollIntervalSeconds` is set to `0` for a CR, the App Framework will not perform a check until the configMap `status` field is updated manually. See [Manual initiation of app management](#manual_initiation_of_app_management). - -## Add a persistent storage volume to the Operator pod - -Note:- If the persistent storage volume is not configured for the Operator, by default, the App Framework uses the main memory(RAM) as the staging area for app package downloads. In order to avoid pressure on the main memory, it is strongly advised to use a persistent volume for the operator pod. - -1. Create the persistent volume used by the Operator pod to cache apps and add-ons: - -```yaml -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: operator-volume-claim -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 8Gi - storageClassName: gp2 -``` - -2. Associate the persistent volume with the Operator pod by updating the Operator configuration: - -```yaml -volumes: -- name: app-staging - persistentVolumeClaim: - claimName: operator-volume-claim -``` - -3. Mount the volume on the path: - -```yaml -volumeMounts: -- mountPath: /opt/splunk/appframework/ - name: app-staging -``` - -A full example of the Operator configuration: - -```yaml -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: operator-volume-claim -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 8Gi - storageClassName: gp2 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: splunk-operator -spec: - replicas: 1 - selector: - matchLabels: - name: splunk-operator - template: - metadata: - labels: - name: splunk-operator - spec: - securityContext: - fsGroup: 1001 - serviceAccountName: splunk-operator - containers: - - name: splunk-operator - image: "docker.io/splunk/splunk-operator:2.4.0" - volumeMounts: - - mountPath: /opt/splunk/appframework/ - name: app-staging - imagePullPolicy: IfNotPresent - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: "splunk-operator" - - name: RELATED_IMAGE_SPLUNK_ENTERPRISE - value: "docker.io/splunk/splunk:9.0.3-a2" - - volumes: - - name: app-staging - persistentVolumeClaim: - claimName: operator-volume-claim -``` - - -## Manual initiation of app management -You can prevent the App Framework from automatically polling the remote storage for app changes. By configuring the `appsRepoPollIntervalSeconds` setting to `0`, the App Framework polling is disabled, and the configMap is updated with a new `status` field. The App Framework will perform an initial poll of the remote storage, even when the CR is initialized with polling disabled. - -When you're ready to initiate an app check using the App Framework, manually update the `status` field in the configMap for that CR type to `on`. The 'status' field defaults to 'off'. - -For example, you deployed one Standalone CR with app framework enabled. - -``` -kubectl get standalone -NAME PHASE DESIRED READY AGE -s1 Ready 1 1 13h -``` -As mentioned above, Splunk Operator will create the configMap (assuming `default` namespace) `splunk-default-manual-app-update` with an entry for Standalone CR as below: - -```yaml -apiVersion: v1 -data: - Standalone: |- - status: off - refCount: 1 -kind: ConfigMap -metadata: - creationTimestamp: "2021-08-24T01:04:01Z" - name: splunk-manual-app-update - namespace: default - ownerReferences: - - apiVersion: enterprise.splunk.com/v3 - controller: false - kind: Standalone - name: s1 - uid: ddb9528f-2e25-49be-acd4-4fadde489849 - resourceVersion: "75406013" - selfLink: /api/v1/namespaces/default/configmaps/splunk-manual-app-update - uid: 413c6053-af4f-4cb3-97e0-6dbe7cd17721 - ``` - -To trigger manual checking of apps, update the configMap, and set the `status` field to `on` for the Standalone CR as below: - -```kubectl patch cm/splunk-default-manual-app-update --type merge -p '{"data":{"Standalone":"status: on\nrefCount: 1"}}'``` - -The App Framework will perform its checks, update or install apps, and reset the `status` to `off` when it has completed its tasks. - -To reinstate automatic polling, update the CR `appsRepoPollIntervalSeconds` setting to a value greater than 0. - -NOTE: All CRs of the same type must have polling enabled, or disabled. For example, if `appsRepoPollIntervalSeconds` is set to '0' for one Standalone CR, all other Standalone CRs must also have polling disabled. Use the `kubectl` command to identify all CRs of the same type before updating the polling interval. You can experience unexpected polling behavior if there are CRs configured with a mix of polling enabled and disabled. - -## App Framework Limitations - -The App Framework does not preview, analyze, verify versions, or enable Splunk Apps and Add-ons. The administrator is responsible for previewing the app or add-on contents, verifying the app is enabled, and that the app is supported with the version of Splunk Enterprise deployed in the containers. For Splunk app packaging specifications see [Package apps for Splunk Cloud or Splunk Enterprise](https://dev.splunk.com/enterprise/docs/releaseapps/packageapps/) in the Splunk Enterprise Developer documentation. The app archive files must end with .spl or .tgz; all other files are ignored. - -1. The App Framework has no support to remove an app or add-on once it’s been deployed. To disable an app, update the archive contents located in the App Source, and set the app.conf state to disabled. - -2. The App Framework defines one worker per CR type. For example, if you have multiple clusters receiveing app updates, a delay while managing one cluster will delay the app updates to the other cluster. - -## Setup Azure bob access with Managed Indentity - -Azure Managed identities can be used to provide IAM access to the blobs. With managed identities, the AKS nodes, that host the pods, can retrieve a OAuth token that provides authorization for the Splunk operator pod to read the app packages stored in the Azure Storage account. The key point here is that the AKS node is associated with a Managed Identity and this managed identity is given a `role` for read access called `Storage Blob Data Reader` to the azure storage account. - -Here are the steps showing an example of assiging managed identity: - -*Assumptions:* - -Familiarize yourself with [AKS managed identity concepts](https://learn.microsoft.com/en-us/azure/aks/use-managed-identity) - -The names used below, such as resource-group name and AKS cluster name, are for examples purpose, please change them to the values as per your setup. - -These steps cover creating resource group and AKS cluster also but you can skip them if you already have them created. - -1. Create an Azure resource group - -``` -az group create --name splunkOperatorResourceGroup --location westus2 -``` - -2. Create AKS Cluster - -``` -az aks create -g splunkOperatorResourceGroup -n splunkOperatorCluster --enable-managed-identity -``` - -3. Get credentials to access cluster -``` -az aks get-credentials --resource-group splunkOperatorResourceGroup --name splunkOperatorCluster -``` -4. Get the Kubelet user managed identity - -Run -``` -$ az identity list -``` - -Find the section that has -agentpool under name - -That is look for the block that contains "name": "splunkOperatorCluster-agentpool" - -``` -{ -"clientId": "a5890776-24e6-4f5b-9b6c-**************", -"id": "/subscriptions/f428689e-c379-4712--**************",/resourcegroups/MC_splunkOperatorResourceGroup_splunkOperatorCluster_westus2/providers/Microsoft.ManagedIdentity/userAssignedIdentities/splunkOperatorCluster-agentpool", -"location": "westus2", -"name": "splunkOperatorCluster-agentpool", -"principalId": "f0f04120-6a36-49bc--**************",", -"resourceGroup": "MC_splunkOperatorResourceGroup_splunkOperatorCluster_westus2", -"tags": {}, -"tenantId": "8add7810-b62a--**************",", -"type": "Microsoft.ManagedIdentity/userAssignedIdentities" -} -``` - -Extract the principalId value from the outout above. Or you can use the following command to get the principalId -``` -$ az identity show --name --resource-group "" --query 'principalId' --output tsv -``` -Example: -``` -$ principalId=$(az identity show --name splunkOperatorCluster-agentpool --resource-group "MC_splunkOperatorResourceGroup_splunkOperatorCluster_westus2" --query 'principalId' --output tsv) -$ echo $principalId -``` -f0f04120-6a36-49bc--************** - -5. Assign read access for Kubelet user managed identity to the storage account - -Use the `principalId` from the above section and assign it to the storage account -``` -az role assignment create --assignee "" --role 'Storage Blob Data Reader' --scope /subscriptions//resourceGroups//providers/Microsoft.Storage/storageAccounts/ -``` -For my example, if is splunkOperatorResourceGroup - -and is mystorageaccount then the command would be: -``` -$ az role assignment create --assignee "f0f04120-6a36-49bc--**************" --role 'Storage Blob Data Reader' --scope /subscriptions/f428689e-c379-4712--**************/resourceGroups/splunkOperatorResourceGroup/providers/Microsoft.Storage/storageAccounts/mystorageaccount -``` -After this command, you can use App framework for Azure blob without secrets. - -Azure Blob Authorization Recommendations: - -Azure allows "Managed Identities" assignment at the "storage accounts" level as well as at specific buckets levels. A managed identity that is assigned read permissions at a storage account level will have read access for all the buckets within that storage account. As a good security practice, you should assign the managed identity to only the specific buckets and not to the whole storage account. - -In contrast to "Managed Identities", Azure allows the "shared access keys" configurable only at the storage accounts level. When using the "secretRef" configuration in the CRD, the underlying secret key will allow both read and write access to the storage account (and all the buckets within it). So, based on your security needs, you may want to consider using "Managed Identities" instead of secrets. Also note that there isn't an automated way of rotating the secret key, so in case you are using these keys, please rotate them at regular intervals of times such as 90 days interval. diff --git a/docs/_configuration/CustomResources.md b/docs/_configuration/CustomResources.md new file mode 100644 index 000000000..7f4b58ccf --- /dev/null +++ b/docs/_configuration/CustomResources.md @@ -0,0 +1,458 @@ +--- +title: Custom Resources Reference +nav_order: 31 +#review_complete: true +--- + +# Custom Resource Reference +{: .no_toc } +The Splunk Operator provides a collection of Custom Resources you can use to manage Splunk Enterprise deployments in your Kubernetes cluster. A Kubernetes Custom Resource is an extention of the Kubernetes API that represents a resource that is not necessarily avalaible in a default Kubernetes installation. Additional documentation about how Custom Resources are used within a Kubernetes cluster can be found on the [Kubernetes docs page - Custom Resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) + +This page is intended to be a reference for all Custom Resources included with a Splunk Operator deployment. For examples on how to use these custom resources, please see [Example Deployments](/configuration/Examples). + + +#### Table of contents +{: .no_toc } +- TOC +{:toc} + + +## Metadata Parameters + +All resources in Kubernetes include a `metadata` section. You can use this to define a name for a specific instance of the resource, and which namespace you would like the resource to reside within + +| Key | Type | Description | +| --------- | ------ | ----------------------------------------------------------------------------------------------------------- | +| name | string | Each instance of your resource is distinguished using this name. | +| namespace | string | Your instance will be created within this namespace. You must ensure that this namespace exists beforehand. | + +If you do not provide a `namespace`, you current context will be used. + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: Standalone +metadata: + name: s1 + namespace: splunk + finalizers: + - enterprise.splunk.com/delete-pvc + annotations: + service.beta.kubernetes.io/azure-load-balancer-internal: "true" +``` + +{: .note } +The `enterprise.splunk.com/delete-pvc` finalizer is optional, and may be used to tell the Splunk Operator that you would like it to remove all the Persistent Volumes associated with the instance when you delete it. \ +Additional documentation about Persistent Volumes can be found on the [Kubernetes docs page - Persistent Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) + + +## Common Spec Parameters for All Resources + +The `spec` section is used to define the desired state for a resource. All custom resources provided by the Splunk Operator include the following configuration parameters. + +| Key | Type | Description | +| ----------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------- | +| image | string | Container image to use for pod instances - overrides `RELATED_IMAGE_SPLUNK_ENTERPRISE` environment variable | +| imagePullPolicy | string | Sets pull policy for all images, this can be either `Always`, or the default `IfNotPresent` | +| livenessInitialDelaySeconds | number | Sets the initialDelaySeconds for Liveness probe (default: 300) | +| readinessInitialDelaySeconds | number | Sets the initialDelaySeconds for Readiness probe (default: 10) | +| extraEnv | [EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#envvar-v1-core) | Sets the extra environment variables to be passed to the Splunk instance containers.

**Warning:** Setting environment variables used by Splunk or Ansible will affect Splunk installation and operation | +| schedulerName | string | Name of [Scheduler](https://kubernetes.io/docs/concepts/scheduling/kube-scheduler/) to use for pod placement (default: `default-scheduler`) | +| affinity | [Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#affinity-v1-core) | [Kubernetes Affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) rules that control how pods are assigned to particular nodes | +| resources | [ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#resourcerequirements-v1-core) | The settings for allocating [compute resource requirements](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to use for each pod instance. The default settings should be considered for demo/test purposes.

Please see [Hardware Resource Requirements](/installation/Prerequisites#hardware-resources-requirements) for production values. | +| serviceTemplate | [Service](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core) | Template used to create Kubernetes [Services](https://kubernetes.io/docs/concepts/services-networking/service/) | +| topologySpreadConstraint | [TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#topologyspreadconstraint-v1-core) | Template used to create Kubernetes [TopologySpreadConstraint](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/) | + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: Standalone +metadata: + name: s1 + namespace: splunk +spec: + image: splunk/splunk-operator:latest + imagePullPolicy: Always + livenessInitialDelaySeconds: 400 + readinessInitialDelaySeconds: 390 + extraEnv: + - name: ADDITIONAL_ENV_VAR_1 + value: "test_value_1" + - name: ADDITIONAL_ENV_VAR_2 + value: "test_value_2" + schedulerName: "default-scheduler" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: topology.kubernetes.io/zone + operator: In + values: + - antarctica-east1 + - antarctica-west1 + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: another-node-label-key + operator: In + values: + - another-node-label-value + resources: + requests: + memory: "512Mi" + cpu: "0.1" + limits: + memory: "8Gi" + cpu: "4" + serviceTemplate: + spec: + type: LoadBalancer + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: zone + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + foo: bar +``` + + +## Common Spec Parameters for Splunk Enterprise Resources + +The following additional configuration parameters may be used for all Splunk Enterprise resources, including: + - `Standalone` + - `LicenseManager` + - `SearchHeadCluster` + - `ClusterManager` + - `IndexerCluster` + +| Key | Type | Description | +| ---------------------- | ----------------- | ----------------------------------------------------------------------------- | +| etcVolumeStorageConfig | StorageClassSpec | Storage class spec for Splunk etc volume as described in [StorageClass](/configuration/StorageClass) | +| varVolumeStorageConfig | StorageClassSpec | Storage class spec for Splunk var volume as described in [StorageClass](/configuration/StorageClass) | +| volumes | [Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#volume-v1-core) | List of one or more [Kubernetes volumes](https://kubernetes.io/docs/concepts/storage/volumes/). These will be mounted in all container pods as as `/mnt/` | +| defaults | string | Inline map of [Splunk Ansible default.yml](https://github.com/splunk/splunk-ansible/blob/develop/docs/advanced/default.yml.spec.md) overrides used to initialize the environment | +| defaultsUrl | string | Full path or URL for one or more [Splunk Ansible default.yml](https://github.com/splunk/splunk-ansible/blob/develop/docs/advanced/default.yml.spec.md) files, separated by commas | +| licenseUrl | string | Full path or URL for a Splunk Enterprise license file | +| licenseManagerRef | [ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#objectreference-v1-core) | Reference to a Splunk Operator managed `LicenseManager` instance (via `name` and optionally `namespace`) to use for licensing | +| clusterManagerRef | [ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#objectreference-v1-core) | Reference to a Splunk Operator managed `ClusterManager` instance (via `name` and optionally `namespace`) to use for indexing | +| monitoringConsoleRef | string | Logical name assigned to the Monitoring Console pod. You can set the name before or after the MC pod creation. | +| serviceAccount | [ServiceAccount](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) | Represents the service account used by the pods deployed by the CRD | +| imagePullSecrets | [imagePullSecrets](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) | Config to pull images from private registry. Use in conjunction with `image` config from [common spec](#common-spec-parameters-for-all-resources) | + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: Standalone +metadata: + name: s1 + namespace: splunk +spec: + etcVolumeStorageConfig: + storageClassName: gp2 + storageCapacity: 15Gi + varVolumeStorageConfig: + storageClassName: customStorageClass + storageCapacity: 25Gi + volumes: + - name: licenses + configMap: + name: splunk-licenses + # defaults: {} + # defaultsUrl: "" + # licenseUrl: "" + licenseManagerRef: + name: example + clusterManagerRef: + name: example + # monitoringConsoleRef: "" + serviceAccount: custom-serviceaccount + # imagePullSecrets: "" +``` + + +## SmartStore Resource Spec Parameters + +The `smartstore` section contains the following SmartStore configuration parameters and may be used for the `Standalone` and `ClusterManager` Splunk Enterprise resources. + +| Key | Type | Description | +| ---------- | ------- | ------------------------------------------------- | +| cacheManager | object | Defines Cache manager settings | +| cacheManager.evictionPadding | integer | Additional size beyond 'minFreeSize' before eviction kicks in | +| cacheManager.evictionPolicy | string | Eviction policy to use | +| cacheManager.hotlistBloomFilterRecencyHours | integer | Time period relative to the bucket's age, during which the bloom filter file is protected from cache eviction | +| cacheManager.hotlistRecencySecs | integer | Time period relative to the bucket's age, during which the bucket is protected from cache eviction | +| cacheManager.maxCacheSize | integer | Max cache size per partition | +| cacheManager.maxConcurrentDownloads | integer | Maximum number of buckets that can be downloaded from remote storage in parallel | +| cacheManager.maxConcurrentUploads | integer | Maximum number of buckets that can be uploaded to remote storage in parallel | +| defaults | object | Default configuration for indexes | +| defaults.maxGlobalDataSizeMB | integer | MaxGlobalDataSizeMB defines the maximum amount of space for warm and cold buckets of an index | +| defaults.maxGlobalRawDataSizeMB | integer | MaxGlobalDataSizeMB defines the maximum amount of cumulative space for warm and cold buckets of an index | +| defaults.volumeName | string | Remote Volume name | +| indexes[] | array | List of Splunk indexes defined as a IndexSpec object | +| IndexSpec | object | IndexSpec defines Splunk index name and storage | +| IndexSpec.hotlistBloomFilterRecencyHours | integer | Time period relative to the bucket's age, during which the bloom filter file is protected from cache eviction | +| IndexSpec.hotlistRecencySecs | integer | Time period relative to the bucket's age, during which the bucket is protected from cache eviction | +| IndexSpec.maxGlobalDataSizeMB | integer | MaxGlobalDataSizeMB defines the maximum amount of space for warm and cold buckets of an index | +| IndexSpec.maxGlobalRawDataSizeMB | integer | MaxGlobalDataSizeMB defines the maximum amount of cumulative space for warm and cold buckets of an index | +| IndexSpec.name | string | Splunk index name | +| IndexSpec.remotePath | string | Index location relative to the remote volume path | +| IndexSpec.volumeName | string | Remote Volume name | +| volumes[] | array | List of remote storage volumes defined as a VolumeSpec object | +| VolumeSpec | object | VolumeSpec defines remote volume config | +| VolumeSpec.endpoint | string | Remote volume URI | +| VolumeSpec.name | string | Remote volume name | +| VolumeSpec.path | string | Remote volume path | +| VolumeSpec.provider | string | App Package Remote Store provider. Supported values: aws, minio, azure. | +| VolumeSpec.region | string | Region of the remote storage volume where apps reside. Used for aws, if provided. Not used for minio and azure. | +| VolumeSpec.secretRef | string | Secret object name | +| VolumeSpec.storageType | string | Remote Storage type. Supported values: s3, blob. s3 works with aws or minio providers, whereas blob works with azure provider. | + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: Standalone +metadata: + name: s1 + namespace: splunk +spec: + smartstore: + defaults: + maxGlobalDataSizeMB: 50000 + maxGlobalRawDataSizeMB: 100000 + volumeName: msos_s2s3_vol + indexes: + - name: salesdata1 + remotePath: $_index_name + volumeName: msos_s2s3_vol + hotlistBloomFilterRecencyHours: 360 + hotlistRecencySecs: 86400 + maxGlobalDataSizeMB: 50000 + maxGlobalRawDataSizeMB: 100000 + - name: salesdata2 + remotePath: $_index_name + volumeName: msos_s2s3_vol + - name: salesdata3 + remotePath: $_index_name + volumeName: msos_s2s3_vol + volumes: + - name: msos_s2s3_vol + path: + endpoint: + secretRef: s3-secret + provider: aws + region: ap-southeast-2 + storageType: s3 +``` + + +## App Framework Resource Spec Parameters + +The `appRepo` section contains the App Framework configuration parameters listed below and may be used the following Splunk Enterprise resources: + - `Standalone` + - `LicenseManager` + - `MonitoringConsole` + - `SearchHeadCluster` + - `ClusterManager` + + +| Key | Type | Description | +| ---------- | ------- | ------------------------------------------------- | +| appSources[] | array | List of App sources on remote storage | +| AppSourceSpec | object | AppSourceSpec defines list of App package (*.spl, *.tgz) locations on remote volumes | +| AppSourceSpec.location | string | Location relative to the volume path | +| AppSourceSpec.name | string | Logical name for the set of apps placed in this location. Logical name must be unique to the appRepo | +| AppSourceSpec.scope | string | Scope of the App deployment: cluster, local. Scope determines whether the App(s) is/are installed locally or cluster-wide | +| AppSourceSpec.volumeName | string | Remote Storage Volume name | +| appsRepoPollIntervalSeconds | string | Remote Storage Volume name | +| defaults | object | Defines the default configuration settings for App sources | +| defaults.scope | string | Scope of the App deployment: cluster, local. Scope determines whether the App(s) is/are installed locally or cluster-wide | +| defaults.volumeName | string | Remote Storage Volume name | +| volumes[] | array | List of remote storage volumes | +| VolumeSpec | object | VolumeSpec defines remote volume config | +| VolumeSpec.endpoint | string | Remote volume URI | +| VolumeSpec.name | string | Remote volume name | +| VolumeSpec.path | string | Remote volume path | +| VolumeSpec.provider | string | App Package Remote Store provider. Currently supported proiders are aws, minio and azure | +| VolumeSpec.region | string | Region of the remote storage volume where apps reside. Not required for azure. | +| VolumeSpec.secretRef | string | Secret object name | +| VolumeSpec.storageType | string | Remote Storage type. Possible values are s3 (works with aws and minio) or blob (works with azure) | + + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: Standalone +metadata: + name: s1 + namespace: splunk +spec: + appRepo: + appsRepoPollIntervalSeconds: 900 + defaults: + volumeName: volume_app_repo_au + scope: cluster + appSources: + - name: searchApps + location: searchAppsLoc/ + - name: machineLearningApps + location: machineLearningAppsLoc/ + - name: adminApps + location: adminAppsLoc/ + scope: local + volumes: + - name: volume_app_repo_au + storageType: s3 + provider: aws + path: bucket-app-framework/shcLoc-au/ + endpoint: https://s3-ap-southeast-2.amazonaws.com + region: ap-southeast-2 + secretRef: s3-secret +``` + + +## LicenseManager Resource Spec Parameters + +Please see [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources) and [Common Spec Parameters for All Splunk Enterprise Resources](#common-spec-parameters-for-all-splunk-enterprise-resources). The `LicenseManager` resource does not provide any additional configuration parameters. + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: LicenseManager +metadata: + name: s1 + namespace: splunk +spec: + volumes: + - name: licenses + configMap: + name: splunk-licenses + licenseUrl: /mnt/licenses/enterprise.lic +``` + +## MonitoringConsole Resource Spec Parameters + +Use the Monitoring Console to view detailed topology and performance information about your Splunk Enterprise deployment. See [What can the Monitoring Console do?](https://docs.splunk.com/Documentation/Splunk/latest/DMC/WhatcanDMCdo) in the Splunk Enterprise documentation. + +The Splunk Operator now includes a CRD for the Monitoring Console (MC). This offers a number of advantages available to other CR's, including: customizable resource allocation, app management, and license management. + +* An MC pod is not created automatically in the default namespace when using other Splunk Operator CR's. +* When upgrading to the latest Splunk Operator, any previously automated MC pods will be deleted. +* To associate a new MC pod with an existing CR, you must update any CR's and add the `monitoringConsoleRef` parameter. + +The MC pod is referenced by using the `monitoringConsoleRef` parameter. There is no preferred order when running an MC pod; you can start the pod before or after the other CR's in the namespace. When a pod that references the `monitoringConsoleRef` parameter is created or deleted, the MC pod will automatically update itself and create or remove connections to those pods. + +```yaml +apiVersion: enterprise.splunk.com/v3 +kind: MonitoringConsole +metadata: + name: example-mc + finalizers: + - enterprise.splunk.com/delete-pvc + +``` + + +## Standalone Resource Spec Parameters + +In addition to [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources), [Common Spec Parameters for All Splunk Enterprise Resources](#common-spec-parameters-for-all-splunk-enterprise-resources), and [SmartStore Resource Spec Parameters](#smartstore-resource-spec-parameters). The `Standalone` resource provides the following `Spec` configuration parameters. + +| Key | Type | Description | +| ---------- | ------- | ------------------------------------------------- | +| replicas | integer | The number of standalone replicas (defaults to 1) | + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: Standalone +metadata: + name: s1 + namespace: splunk + labels: + app: SplunkStandAlone + type: Splunk + finalizers: + - enterprise.splunk.com/delete-pvc +spec: + replicas: 1 +``` + +## ClusterManager Resource Spec Parameters + +Please see [SmartStore Resource Spec Parameters](#smartstore-resource-spec-parameters) The `ClusterManager` resource does not provide any additional configuration parameters. + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: ClusterManager +metadata: + name: example-cm + namespace: splunk +spec: + smartstore: + defaults: + maxGlobalDataSizeMB: 50000 + maxGlobalRawDataSizeMB: 100000 + volumeName: msos_s2s3_vol + indexes: + - name: salesdata1 + remotePath: $_index_name + volumeName: msos_s2s3_vol + hotlistBloomFilterRecencyHours: 360 + hotlistRecencySecs: 86400 + maxGlobalDataSizeMB: 50000 + maxGlobalRawDataSizeMB: 100000 + - name: salesdata2 + remotePath: $_index_name + volumeName: msos_s2s3_vol + - name: salesdata3 + remotePath: $_index_name + volumeName: msos_s2s3_vol + volumes: + - name: msos_s2s3_vol + path: + endpoint: + secretRef: s3-secret + provider: aws + region: ap-southeast-2 + storageType: s3 +``` + + +## IndexerCluster Resource Spec Parameters + +In addition to [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources) and [Common Spec Parameters for All Splunk Enterprise Resources](#common-spec-parameters-for-all-splunk-enterprise-resources), the `IndexerCluster` resource provides the following `Spec` configuration parameters. + +| Key | Type | Description | +| ---------- | ------- | ----------------------------------------------------- | +| replicas | integer | The number of indexer cluster members (defaults to 1) | + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: IndexerCluster +metadata: + name: idxc1 + namespace: splunk +spec: + replicas: 3 + clusterManagerRef: + name: example-cm + namespace: splunk +``` + +{: .note } +`clusterManagerRef` is required field in case of IndexerCluster resource since it will be used to connect the IndexerCluster to ClusterManager resource. + + +## SearchHeadCluster Resource Spec Parameters + +In addition to [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources) and [Common Spec Parameters for All Splunk Enterprise Resources](#common-spec-parameters-for-all-splunk-enterprise-resources). The `SearchHeadCluster` resource provides the following `Spec` configuration parameters. + +| Key | Type | Description | +| -------- | ------- | ------------------------------------------------------------ | +| replicas | integer | The number of search heads cluster members (minimum of 3, which is the default) | + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: SearchHeadCluster +metadata: + name: shc1 + namespace: splunk +spec: + replicas: 5 +``` + diff --git a/docs/Examples.md b/docs/_configuration/Examples.md similarity index 82% rename from docs/Examples.md rename to docs/_configuration/Examples.md index d395d1efc..4140d8775 100644 --- a/docs/Examples.md +++ b/docs/_configuration/Examples.md @@ -1,49 +1,22 @@ -# Configuring Splunk Enterprise Deployments +--- +title: Example Deployments +nav_order: 28.1 +#nav_exclude: true +--- +# Example Splunk Enterprise Deployments +{: .no_toc } This document includes various examples for configuring Splunk Enterprise deployments with the Splunk Operator. +For more information about the custom resources that you can use with the Splunk Operator, refer to the [Custom Resource Reference](/configuration/CustomResources). +#### Table of contents +{: .no_toc } +- TOC +{:toc} -- [Configuring Splunk Enterprise Deployments](#configuring-splunk-enterprise-deployments) - - [Creating a Clustered Deployment](#creating-a-clustered-deployment) - - [Indexer Clusters](#indexer-clusters) - - [Cluster Manager](#cluster-manager) - - [Indexer cluster peers](#indexer-cluster-peers) - - [Scaling cluster peers using replicas](#scaling-cluster-peers-using-replicas) - - [Scaling cluster peers using pod autoscaling](#scaling-cluster-peers-using-pod-autoscaling) - - [Create a search head for your index cluster](#create-a-search-head-for-your-index-cluster) - - [Another Cluster Manager example](#another-cluster-manager-example) - - [Monitoring Console](#monitoring-console) - - [Search Head Clusters](#search-head-clusters) - - [Cluster Services](#cluster-services) - - [Cleaning Up](#cleaning-up) - - [SmartStore Index Management](#smartstore-index-management) - - [Using Default Settings](#using-default-settings) - - [Installing Splunk Apps](#installing-splunk-apps) - - [Creating a LicenseManager Using a ConfigMap](#creating-a-licensemanager-using-a-configmap) - - [Configuring Standalone to use License Manager](#configuring-standalone-to-use-license-manager) - - [Configuring Indexer Clusters to use License Manager](#configuring-indexer-clusters-to-use-license-manager) - - [Using an External License Manager](#using-an-external-license-manager) - - [Configuring pass4Symmkey:](#configuring-pass4symmkey) - - [Approach 1](#approach-1) - - [Approach 2](#approach-2) - - [Configuring license\_master\_url:](#configuring-license_master_url) - - [Using an External Indexer Cluster](#using-an-external-indexer-cluster) - - [Configuring IDXC pass4Symmkey:](#configuring-idxc-pass4symmkey) - - [Approach 1](#approach-1-1) - - [Approach 2](#approach-2-1) - - [Configuring cluster\_master\_url:](#configuring-cluster_master_url) - - [Managing global kubernetes secret object](#managing-global-kubernetes-secret-object) - - [Creating global kubernetes secret object](#creating-global-kubernetes-secret-object) - - [Reading global kubernetes secret object](#reading-global-kubernetes-secret-object) - - [Updating global kubernetes secret object](#updating-global-kubernetes-secret-object) - - [Deleting global kubernetes secret object](#deleting-global-kubernetes-secret-object) - -For more information about the custom resources that you can use with the Splunk Operator, refer to the [Custom Resource Guide](CustomResources.md). - -## Creating a Clustered Deployment +## Creating a Standalone Deployment -The two basic building blocks of Splunk Enterprise infrastructure are search heads and indexers. A `Standalone` resource can be used to create a single instance -that can perform either, or both of these roles. +The two basic building blocks of Splunk Enterprise infrastructure are search heads and indexers. A `Standalone` resource can be used to create a single instance that can perform either, or both of these roles. ```yaml apiVersion: enterprise.splunk.com/v4 @@ -56,12 +29,15 @@ metadata: The passwords for the instance are generated automatically. To review the passwords, please refer to the [Reading global kubernetes secret object](#reading-global-kubernetes-secret-object) instructions. +## Creating a Clustered Deployment + ### Indexer Clusters When customers outgrow the capabilites of single instance for indexing and search, they will scale the infrastructure up to an [indexer cluster](https://docs.splunk.com/Documentation/Splunk/latest/Indexer/Aboutindexesandindexers). The Splunk Operator makes creation of a cluster easy by utilizing a `ClusterManager` resource for Cluster Manager, and using the `IndexerCluster` resource for the cluster peers: #### Cluster Manager +{: .no_toc } ```yaml cat <-secret -o jsonpath='{.data.password}' | base64 --decode ``` -See [Configuring Ingress](Ingress.md) for guidance on making your Splunk Enterprise clusters accessible from outside of Kubernetes. +See [Configuring Ingress](/configuration/Ingress) for guidance on making your Splunk Enterprise clusters accessible from outside of Kubernetes. ### Cleaning Up - +{: .no_toc } As these examples demonstrate, the Splunk Operator makes it easy to create and manage clustered deployments of Splunk Enterprise. Given the reduced complexity, the comparable resource requirements from leveraging containers, and the ability to easily start small and scale as necessary, we recommend that you use the `IndexerCluster` and `SearchHeadCluster` resources when creating deployments using the Splunk Operator. To remove the resources created from this example, run: @@ -411,7 +396,7 @@ kubectl delete -n splunk-opertaor clustermanager cm ## SmartStore Index Management -Indexes can be managed through the Splunk Operator. Every index configured through the Splunk Operator must be SmartStore enabled. See [SmartStore Resource Guide](SmartStore.md). +Indexes can be managed through the Splunk Operator. Every index configured through the Splunk Operator must be SmartStore enabled. See [SmartStore Resource Guide](/configuration/SmartStore). ## Using Default Settings @@ -462,15 +447,16 @@ app installation. Inline `defaults` are always processed last, after any `defaultsUrl` files. Any password management related configuration via `defaults` and `defaultsUrl` -has been disabled. Please review [`PasswordManagement.md`](PasswordManagement.md) +has been disabled. Please review [`PasswordManagement.md`](/configuration/PasswordManagement) and [`Managing global kubernetes secret object`](#managing-global-kubernetes-secret-object) for more details. ## Installing Splunk Apps -*Note that this requires using the Splunk Enterprise container version 9.0.0 or later* +{: .note } +This requires using the Splunk Enterprise container version 9.0.0 or later* -With the Splunk Operator 2.0 release, new App Framework is available to centrally store and deploy apps. See [AppFramework](AppFramework.md) for information and examples. +With the Splunk Operator 2.0 release, new App Framework is available to centrally store and deploy apps. See [AppFramework](/configuration/AppFramework) for information and examples. ## Creating a LicenseManager Using a ConfigMap @@ -513,9 +499,8 @@ the `enterprise.lic` file within it. licenseUrl: "/mnt/licenses/enterprise1.lic,/mnt/licenses/enterprise2.lic" ``` -Note that `licenseUrl` may specify a local path or URL such as -"https://myco.com/enterprise.lic", and the `volumes` parameter can -be used to mount any type of [Kubernetes Volumes](https://kubernetes.io/docs/concepts/storage/volumes/). +{: .note } +`licenseUrl` may specify a local path or URL such as "https://myco.com/enterprise.lic", and the `volumes` parameter can be used to mount any type of [Kubernetes Volumes](https://kubernetes.io/docs/concepts/storage/volumes/). ## Configuring Standalone to use License Manager @@ -537,7 +522,7 @@ spec: ## Configuring Indexer Clusters to use License Manager -While configuring [`Indexer Clusters`](Examples.md#indexer-clusters) to use the `LicenseManager`, you need to add `licenseManagerRef` only to the `ClusterManager` spec as follows: +While configuring [`Indexer Clusters`](#indexer-clusters) to use the `LicenseManager`, you need to add `licenseManagerRef` only to the `ClusterManager` spec as follows: ```yaml cat <` +1. Verify the namespace. You can retrieve the namespace in the current context using `kubectl config view --minify --output 'jsonpath={..namespace}'`. Make a note of the output. If the command doesn't display an output it indicates that we are in the `default` namespace. +{: .note } +If you already have a desired namespace, you can set current context to the same using the following command: `kubectl config set-context --current --namespace=` -2. Gather the password values for the secret tokens you want to configure. To see all available secret tokens defined for the global kubernetes secret object, review [password management](PasswordManagement.md#splunk-secret-tokens-in-the-global-secret-object) +2. Gather the password values for the secret tokens you want to configure. To see all available secret tokens defined for the global kubernetes secret object, review [password management](/configuration/PasswordManagement#splunk-secret-tokens-in-the-global-secret-object) 3. Create a kubernetes secret object referencing the namespace. Example: splunk-`-secret. In the example below, we are creating the global kubernetes secret object, defining the default administrator and pass4Symmkey tokens, and passing in the values. @@ -775,9 +768,9 @@ type: Opaque ``` The kubectl command line tool can be used to decode the splunk secret tokens with the following command: - +{% raw %} `kubectl get secret splunk--secret -o go-template='{{range $k,$v := .data}}{{printf "%s: " $k}}{{if not $v}}{{$v}}{{else}}{{$v | base64decode}}{{end}}{{"\n"}}{{end}}'` - +{% endraw %} A sample global kubernetes secret object with tokens decoded looks like: ``` @@ -793,7 +786,7 @@ shc_secret: dGGXnNogsL8V4yhp1bajbrZ5 Use the kubectl command to update the global kubernetes secret object: 1. Base64 encode the plain-text value of the secret token using the following command: `echo -n | base64` -2. Obtain the key name for the secret token you are populating. The list of tokens is available in [password management](PasswordManagement.md#splunk-secret-tokens-in-the-global-secret-object). +2. Obtain the key name for the secret token you are populating. The list of tokens is available in [password management](/configuration/PasswordManagement#splunk-secret-tokens-in-the-global-secret-object). 3. Update the global kubernetes secret object using the key and the encoded value: `kubectl patch secret splunk--secret -p='{"data":{"": ""}}' -v=1` ### Deleting global kubernetes secret object diff --git a/docs/Ingress.md b/docs/_configuration/Ingress.md similarity index 93% rename from docs/Ingress.md rename to docs/_configuration/Ingress.md index da5fac795..48fa9f535 100644 --- a/docs/Ingress.md +++ b/docs/_configuration/Ingress.md @@ -1,4 +1,10 @@ +--- +title: Ingress +nav_order: 25 +--- + # Configuring Ingress +{: .no_toc } Using `port-forward` is great for testing, but you will ultimately want to make it easier to access your Splunk cluster outside of Kubernetes. A common approach is through the use of [Kubernetes Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/). @@ -28,20 +34,24 @@ We provide some examples below for configuring a few of the most popular Ingress Before deploying an example, you will need to review the yaml and replace “example.com” with the domain name you would like to use and replace “example” in the service names with the name of your custom resource object. You will also need to point your DNS for all the desired hostnames to the IP addresses of your ingress load balancer. +#### Table of contents +{: .no_toc } +- TOC +{:toc} -#### Important Notes on using Splunk on Kubernetes +### Important Notes on using Splunk on Kubernetes -#### Load Balancer Requirements +##### Load Balancer Requirements When configuring ingress for use with Splunk Forwarders, the configured ingress load balancer must resolve to two or more IPs. This is required so the auto load balancing capability of the forwarders is preserved. -#### Splunk default network ports +##### Splunk default network ports When creating a new Splunk instance on Kubernetes, the default network ports will be used for internal communication such as internal logs, replication, and others. Any change in how these ports are configured needs to be consistent across the cluster. For Ingress we recommend using separate ports for encrypted and non-encrypted traffic. In this documentation we will use port 9998 for encrypted data coming from outside the cluster, while keeping the default 9997 for non-encrypted intra-cluster communication. For example, this [ServiceTemplate configuration](#serviceTemplate) creates a standalone instance with port 9998 exposed. -#### Indexer Discovery is not supported +##### Indexer Discovery is not supported Indexer Discovery is not supported on a Kubernetes cluster. Instead, the Ingress controllers will be responsible to connect forwarders to peer nodes in Indexer clusters. @@ -57,7 +67,7 @@ Most scenarios for Istio will require the configuration of a Gateway and a Virtu You can configure Istio to provide direct access to Splunk Web. -#### Standalone Configuration +##### Standalone Configuration 1. Create a Gateway to receive traffic on port 80 @@ -112,7 +122,7 @@ kubectl get svc -n istio-system http:// ``` -#### Multiple Hosts and HEC Configuration +##### Multiple Hosts and HEC Configuration If your deployment has multiple hosts such as Search Heads and Cluster Manager, use this example to configure Splunk Web access, and HTTP Event Collector port. Follow the steps here [HEC Documentation](https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector) to learn how to create a HEC token and how to send data using HTTP. @@ -297,12 +307,12 @@ kubectl get svc -n istio-system ### Configuring Ingress for Splunk Forwarder data with TLS It is highly recommended that you always use TLS encryption for your Splunk Enterprise endpoints. The following sections will cover the two main configurations supported by Istio. -#### Splunk Forwarder data with end-to-end TLS +##### Splunk Forwarder data with end-to-end TLS In this configuration Istio passes the encrypted traffic to Splunk Enterprise without any termination. Note that you need to configure the TLS certificates on the Forwarder as well as any Splunk Enterprise indexers, cluster peers, or standalone instances. -End-to-End Configuration +End-to-End Configuration When using TLS for Ingress, we recommend you add an additional port for secure communication. By default, port 9997 will be assigned for non-encrypted traffic and you can use any other available port for secure communications. @@ -379,21 +389,24 @@ spec: number: 9998 ``` -*Note*: this TLS example requires that `outputs.conf` on your forwarders includes the setting `tlsHostname = splunk.example.com`. Istio requires the TLS header to be defined so it to know which indexers to forward the traffic to. If this parameter is not defined, your forwarder connections will fail. +{: .note } +This TLS example requires that `outputs.conf` on your forwarders includes the setting `tlsHostname = splunk.example.com`. Istio requires the TLS header to be defined so it to know which indexers to forward the traffic to. If this parameter is not defined, your forwarder connections will fail. If you only have one indexer cluster that you would like to use as the destination for all S2S traffic, you can optionally replace `splunk.example.com` in the above examples with the wildcard `*`. When you use this wildcard, you do not have to set the `tlsHostname` parameter in `outputs.conf` on your forwarders. -4. Deploy an app to the standalone instance with the inputs.conf settings needed to open port 9998 and configure the relevant TLS settings. For details on app management using the Splunk Operator, see [Using Apps for Splunk Configuration](https://splunk.github.io/splunk-operator/Examples.html#installing-splunk-apps). +4. Deploy an app to the standalone instance with the inputs.conf settings needed to open port 9998 and configure the relevant TLS settings. For details on app management using the Splunk Operator, see [Using Apps for Splunk Configuration](/configuration/Examples#installing-splunk-apps). Configure the Forwarder's outputs.conf and the Indexer's inputs.conf using the documentation [Configure Secure Forwarding](https://docs.splunk.com/Documentation/Splunk/latest/Security/Aboutsecuringdatafromforwarders) -#### Splunk Forwarder data with TLS Gateway Termination +##### Splunk Forwarder data with TLS Gateway Termination -In this configuration, Istio is terminating the encryption at the Gateway and forwarding the decrypted traffic to Splunk Enterprise. Note that in this case the Forwarder's outputs.conf should be configured for TLS, while the Indexer's input.conf should be configured to accept non-encrypted traffic. +In this configuration, Istio is terminating the encryption at the Gateway and forwarding the decrypted traffic to Splunk Enterprise. +{: .note } +In this case the Forwarder's outputs.conf should be configured for TLS, while the Indexer's input.conf should be configured to accept non-encrypted traffic. -End-to-End Configuration +End-to-End Configuration 1. Create a TLS secret with the certificates needed to decrypt traffic. These are the same commands used on your Indexer to terminate TLS: @@ -445,7 +458,8 @@ spec: number: 9997 host: splunk-standalone-standalone-service ``` -Note that the Virtual Service no longer handles TLS since it has been terminated at the gateway. +{: .note } +The Virtual Service no longer handles TLS since it has been terminated at the gateway. 4. Configure your Forwarder and Indexer or Standalone certificates using the documentation: [Securing data from forwarders](https://docs.splunk.com/Documentation/Splunk/latest/Security/Aboutsecuringdatafromforwarders). @@ -457,7 +471,8 @@ Istio is a popular choice for its Service Mesh capabilities. However, Service Me ## Configuring Ingress Using NGINX -**NOTE**: There are at least 3 flavors of the Nginx Ingress controller. +{: .note } +There are at least 3 flavors of the Nginx Ingress controller. - Kubernetes Ingress Nginx (open source) - Nginx Ingress Open Source (F5's open source version) @@ -558,7 +573,8 @@ There are a few important configurations to be aware of in the TLS configuration * The `nginx.ingress.kubernetes.io/backend-protocol:` annotation requires `"HTTPS"` when TLS is configured on the backend services. * The secretName must reference a [valid TLS secret](https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets). -Note: This example assumes that https is enabled for Splunk Web. +{: .note } +This example assumes that https is enabled for Splunk Web. ``` apiVersion: networking.k8s.io/v1beta1 @@ -607,7 +623,8 @@ spec: ### Configuring Ingress NGINX for Splunk Forwarders with End-to-End TLS -Note: In this example we used port 9997 for non-encrypted communication, and 9998 for encrypted. +{: .note } +In this example we used port 9997 for non-encrypted communication, and 9998 for encrypted. Update the default Ingress NGINX configuration to add the ConfigMap and Service ports: @@ -682,7 +699,7 @@ The Nginx Ingress Controller is an open source version of the F5 product. Please We followed the product's Helm Chart installation guide. It requires a cluster with internet access. [NGINX Ingress Controller Helm Installation]( https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-helm/) -#### Setup Helm +##### Setup Helm ```shell # clone the repo and check out the current production branch @@ -698,7 +715,7 @@ $ helm repo update $ kubectl create -f crds/ ``` -#### Install Ingress +##### Install Ingress ```shell cd deployments/helm-chart @@ -715,7 +732,7 @@ splunk-nginx default 5 2020-10-29 15:03:47.6 EDT deployed nginx-ingr helm upgrade splunk-nginx nginx-stable/nginx-ingress ``` -#### Configure Ingress services +##### Configure Ingress services ##### Configure Ingress for Splunk Web and HEC @@ -771,7 +788,6 @@ status: Enable the global configuration to setup a listener and transport server 1. Create the GlobalConfiguration: - ```yaml apiVersion: k8s.nginx.org/v1alpha1 kind: GlobalConfiguration @@ -800,19 +816,17 @@ spec: ``` 2. Edit the service to establish a node-port for the port being setup as the listener: - 1. List the service: - -```yaml -kubectl get svc -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -splunk-nginx-nginx-ingress LoadBalancer 172.20.195.54 aa725344587a4443b97c614c6c78419c-1675645062.us-east-2.elb.amazonaws.com 80:31452/TCP,443:30402/TCP,30403:30403/TCP 7d1h -``` - -​ 2. Edit the service and add the Splunk Forwarder ingress port: - -``` -kubectl edit service splunk-nginx-nginx-ingress -``` + 1. List the service: + ```yaml + kubectl get svc + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + splunk-nginx-nginx-ingress LoadBalancer 172.20.195.54 aa725344587a4443b97c614c6c78419c-1675645062.us-east-2.elb.amazonaws.com 80:31452/TCP,443:30402/TCP,30403:30403/TCP 7d1h + ``` + + 2. Edit the service and add the Splunk Forwarder ingress port: + ``` + kubectl edit service splunk-nginx-nginx-ingress + ``` Example Service: ```yaml @@ -997,7 +1011,8 @@ spec: - "license-manager.splunk.example.com" ``` -Note that the `credentialName` references the same `secretName` created and managed by the Certificate object. +{: .note } +The `credentialName` references the same `secretName` created and managed by the Certificate object. 3. If you are manually importing your certificates into separate Secrets for each hostname, you can reference these by instead using multiple `port` objects in your Gateway: diff --git a/docs/_configuration/KubernetesQOS.md b/docs/_configuration/KubernetesQOS.md new file mode 100644 index 000000000..2788dbb39 --- /dev/null +++ b/docs/_configuration/KubernetesQOS.md @@ -0,0 +1,76 @@ +--- +title: Kubernetes Quality of Service Classes +nav_order: 27.1 +--- + +## Using Kubernetes Quality of Service Classes (QoS) + +In addition to the guidelines provided in the [reference hardware](/installation/Prerequisites#hardware-resources-requirements), [Kubernetes QoS Classes](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/) can be used to configure CPU/Mem resources allocations that map to your _service level objectives_. For further information on utilizing Kubernetes Quality of Service (QoS) classes, see the table below: + + +| QoS | Summary| Description | +| ---------- | ------- | ------- | +| _Guaranteed_ | _CPU/Mem ```requests``` = CPU/Mem ```limits```_ | _When the CPU and memory ```requests``` and ```limits``` values are equal, the pod is given a QoS class of Guaranteed. This level of service is recommended for Splunk Enterprise ___production environments___._ | +| _Burstable_ | _CPU/Mem ```requests``` < CPU/Mem ```limits```_ | _When the CPU and memory ```requests``` value is set lower than the ```limits``` the pod is given a QoS class of Burstable. This level of service is useful in a user acceptance testing ___(UAT) environment___, where the pods run with minimum resources, and Kubernetes allocates additional resources depending on usage._| +| _BestEffort_ | _No CPU/Mem ```requests``` or ```limits``` are set_ | _When the ```requests``` or ```limits``` values are not set, the pod is given a QoS class of BestEffort. This level of service is sufficient for ___testing, or a small development task___._ | + + +## Examples of Guaranteed and Burstable QoS + +### A Guaranteed QoS Class example: +Set equal ```requests``` and ```limits``` values for CPU and memory to establish a QoS class of Guaranteed. + +{: .note } +A pod will not start on a node that cannot meet the CPU and memory ```requests``` values. + +Example: The minimum resource requirements for a Standalone Splunk Enterprise instance in production are 24 vCPU and 12GB RAM. + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: Standalone +metadata: + name: example +spec: + imagePullPolicy: Always + resources: + requests: + memory: "12Gi" + cpu: "24" + limits: + memory: "12Gi" + cpu: "24" +``` + +### A Burstable QoS Class example: +Set the ```requests``` value for CPU and memory lower than the ```limits``` value to establish a QoS class of Burstable. + +Example: This Standalone Splunk Enterprise instance should start with minimal indexing and search capacity, but will be allowed to scale up if Kubernetes is able to allocate additional CPU and Memory up to the ```limits``` values. + +```yaml +apiVersion: enterprise.splunk.com/v4 +kind: Standalone +metadata: + name: example +spec: + imagePullPolicy: Always + resources: + requests: + memory: "2Gi" + cpu: "4" + limits: + memory: "12Gi" + cpu: "24" +``` + +### A BestEffort QoS Class example: +With no requests or limits values set for CPU and memory, the QoS class is set to BestEffort. The BestEffort QoS is not recommended for use with Splunk Operator. + +### Pod Resources Management + +__CPU Throttling__ + +Kubernetes starts throttling CPUs if a pod's demand for CPU exceeds the value set in the ```limits``` parameter. If your nodes have extra CPU resources available, leaving the ```limits``` value unset will allow the pods to utilize more CPUs. + +__POD Eviction - OOM__ + +As oppose to throttling in case of CPU cycles starvation, Kubernetes will evict a pod from the node if the pod's memory demands exceeds the value set in the ```limits``` parameter. diff --git a/docs/MultisiteExamples.md b/docs/_configuration/MultisiteExamples.md similarity index 89% rename from docs/MultisiteExamples.md rename to docs/_configuration/MultisiteExamples.md index 15139b57c..1ca316970 100644 --- a/docs/MultisiteExamples.md +++ b/docs/_configuration/MultisiteExamples.md @@ -1,18 +1,21 @@ +--- +title: Examples Multisite Deployments +nav_order: 28.2 +#nav_exclude: true +--- + # Configuring Splunk Enterprise Multisite Deployments +{: .no_toc } +This document provides examples to configure a multisite cluster using the splunk-operator. -This document provides examples to configure a multisite cluster using the splunk-operator. +Please refer to the [Example Deployments](/configuration/Examples) for more information and examples about deploying the different Splunk resources in single site mode. -- [Configuring Splunk Enterprise Multisite Deployments](#configuring-splunk-enterprise-multisite-deployments) - - [Multisite Indexer Clusters in Kubernetes](#multisite-indexer-clusters-in-kubernetes) - - [Multipart IndexerCluster](#multipart-indexercluster) - - [Deploy the cluster-manager](#deploy-the-cluster-manager) - - [Deploy the indexer sites](#deploy-the-indexer-sites) - - [Connecting a search-head cluster to a multisite indexer-cluster](#connecting-a-search-head-cluster-to-a-multisite-indexer-cluster) +#### Table of contents +{: .no_toc } +- TOC +{:toc} -Please refer to the [Configuring Splunk Enterprise Deployments Guide](Example.md) -for more information and examples about deploying the different Splunk resources -in single site mode. ## Multisite Indexer Clusters in Kubernetes @@ -148,7 +151,7 @@ metadata: - enterprise.splunk.com/delete-pvc spec: replicas: 3 - image: "splunk/splunk:9.0.3-a2" + image: "splunk/splunk:{{ page.splunk_enterprise_version }}" clusterManagerRef: name: example defaults: |- diff --git a/docs/PasswordManagement.md b/docs/_configuration/PasswordManagement.md similarity index 80% rename from docs/PasswordManagement.md rename to docs/_configuration/PasswordManagement.md index 1d886f23f..17ce88806 100644 --- a/docs/PasswordManagement.md +++ b/docs/_configuration/PasswordManagement.md @@ -1,38 +1,39 @@ +--- +title: Password Management +nav_order: 26 +#nav_exclude: true +--- + # Password Management +{: .no_toc } -- [Password Management](#password-management) - - [Global kubernetes secret object](#global-kubernetes-secret-object) - - [Default behavior of global kubernetes secret object](#default-behavior-of-global-kubernetes-secret-object) - - [Splunk Secret Tokens in the global secret object](#splunk-secret-tokens-in-the-global-secret-object) - - [HEC Token](#hec-token) - - [Default administrator password](#default-administrator-password) - - [pass4Symmkey](#pass4symmkey) - - [IDXC pass4Symmkey](#idxc-pass4symmkey) - - [SHC pass4Symmkey](#shc-pass4symmkey) - - [Information for Splunk Enterprise administrator](#information-for-splunk-enterprise-administrator) - - [Secrets on Docker Splunk](#secrets-on-docker-splunk) - - [SmartStore Access using AWS IAM Role for Service Account](#smartstore-access-using-aws-iam-role-for-service-account) - - [Support for AWS IAM Role for Service Account in Splunk Operator Deployment](#support-for-aws-iam-role-for-service-account-in-splunk-operator-deployment) - -## Global kubernetes secret object -A global kubernetes secret object acts as the source of secret tokens for a kubernetes namespace used by all Splunk Enterprise CR's. It's name follows the format `splunk--secret` where ` represents the namespace we are operating in. The contents of this object are volume mounted on all the pods within a kubernetes namespace. +A global kubernetes secret object acts as the source of secret tokens for a kubernetes namespace used by all Splunk Enterprise CR's. It's name follows the format `splunk--secret` where `` represents the namespace we are operating in. The contents of this object are volume mounted on all the pods within a kubernetes namespace. This approach: - Eliminates any mismatch between operator-generated secrets and admin provided secrets as all secrets are synced into a common object. - Allows for dynamic adoption and modification of secrets. +

+ +#### Table of contents +{: .no_toc } +- TOC +{:toc} + ## Default behavior of global kubernetes secret object Upon the creation of the first Splunk Enterprise CR in a given namespace, the operator checks for the existence of a global kubernetes secret object: - If the object does not exist, - - It creates the global kubernetes secret object with name splunk-`-secret - - It auto-generates, encodes and stores all Splunk Enterprise secret tokens into a global kubernetes secret object for the namespace. Note: SmartStore secret tokens are not generated, and must be created manually. + - It creates the global kubernetes secret object with name `splunk--secret` + - It auto-generates, encodes and stores all Splunk Enterprise secret tokens into a global kubernetes secret object for the namespace. - If the object exists, - It checks for the existence of the Splunk Enterprise secret tokens by key value. - - It auto-generates, encodes, and stores a Splunk Enterprise secret token for any empty keys. Note: SmartStore secret tokens are not generated, and must be created manually. + - It auto-generates, encodes, and stores a Splunk Enterprise secret token for any empty keys. -Note: Before the creation of any Splunk deployments in the kubernetes namespace, the admin can create a global kubernetes secret object using the tokens mentioned below. The operator will use these pre-populated values to deploy. +{: .note } +SmartStore secret tokens are not generated, and must be created manually.

+Before the creation of any Splunk deployments in the kubernetes namespace, the admin can create a global kubernetes secret object using the tokens mentioned below. The operator will use these pre-populated values to deploy. ### Splunk Secret Tokens in the global secret object The configurable Splunk Secret Tokens include: @@ -57,13 +58,13 @@ The configurable Splunk Secret Tokens include: **Key name in global kubernetes secret object**: `shc.secret` **Description**: shc.secret is an authentication token for inter-communication specifically for search head clustering in Splunk Enterprise. -For examples of performing CRUD operations on the global secrets object, see [examples](Examples.md#managing-global-kubernetes-secret-object). For more information on managing kubernetes secret objects refer [kubernetes.io managing secrets](https://kubernetes.io/docs/tasks/configmap-secret/managing-secret-using-kubectl/) +For examples of performing CRUD operations on the global secrets object, see [examples](/configuration/Examples#managing-global-kubernetes-secret-object). For more information on managing kubernetes secret objects refer [kubernetes.io managing secrets](https://kubernetes.io/docs/tasks/configmap-secret/managing-secret-using-kubectl/) ## Information for Splunk Enterprise administrator - The default administrator account cannot be disabled on any Splunk Enterprise instance. The kubernetes operator uses this account to interact with all Splunk Enterprise instances in the namespace. - The passwords managed using the global kubernetes secret object should never be changed using Splunk Enterprise tools (CLI, UI.) -- The default administrator account must use the global kubernetes secret object for any password changes. See [managing global kubernetes secret object](Examples.md#managing-global-kubernetes-secret-object) +- The default administrator account must use the global kubernetes secret object for any password changes. See [managing global kubernetes secret object](/configuration/Examples#managing-global-kubernetes-secret-object) - After initiating a update/delete operation on the global secrets object, the operator will require time to finish setting the changes on the all Splunk Enterprise instances in the namespace during which disruption of splunk services can be expected while the secret updates are happening. A status check on all the Splunk Enterprise cluster tiers is required. ## Secrets on Docker Splunk @@ -90,7 +91,7 @@ Below Example explains the steps required for setting up IAM Service Account Once the Service Account is created, make sure it is annotated with specific IAM Role. Once everything looks good, add service account to splunk custom resource. here is the example for adding it to `Standalone` instance -``` +```yaml apiVersion: enterprise.splunk.com/v4 kind: Standalone metadata: @@ -130,7 +131,7 @@ Make sure the token file mentioned in AWS_WEB_IDENTITY_TOKEN_FILE location is on Follow the steps mentioned above for creating AWS IAM Service Account. Make sure IAM Role only has least amount of privilege necessary reading apps from S3 bucket. Once the service account is created, map this service account to `splunk-operator` deployment. Below is the example -``` +```yaml apiVersion: apps/v1 kind: Deployment metadata: diff --git a/docs/PremiumApps.md b/docs/_configuration/PremiumApps.md similarity index 97% rename from docs/PremiumApps.md rename to docs/_configuration/PremiumApps.md index 16263bb38..dafa81544 100644 --- a/docs/PremiumApps.md +++ b/docs/_configuration/PremiumApps.md @@ -1,3 +1,9 @@ +--- +title: Premium Apps Installation +nav_order: 22 +#nav_exclude: true +--- + # Premium Apps Installation Guide The Splunk Operator automates the installation of Enterprise Security (ES) with support for other premium apps coming in the future releases. This page documents the prerequisites, installation steps, troublshooting steps, and limitations of deploying premium apps using the Splunk Operator. @@ -6,11 +12,11 @@ The Splunk Operator automates the installation of Enterprise Security (ES) with ### Before you begin -* You need the ability to utilize the Splunk Operator [app framework](https://splunk.github.io/splunk-operator/AppFramework.html) method of installation. +* You need the ability to utilize the Splunk Operator [app framework](/configuration/AppFramework) method of installation. * You need the access to the [Splunk ES](https://splunkbase.splunk.com/app/263/) app package. * ES support in Splunk Operator is starting from Splunk Operator Release `2.2.0` which requires Splunk Enterprise `9.0.3-a2` or later. Per the [Splunk Enterprise and Enterprise Security version compatibility matrix](https://docs.splunk.com/Documentation/VersionCompatibility/current/Matrix/CompatMatrix), Splunk ES versions `7.1.0, 7.0.2, 7.0.1, 7.0.0 or 6.6.2` are supported currently. * You need to make sure pod resource specs meet the [ES hardware requirements](https://docs.splunk.com/Documentation/ES/latest/Install/DeploymentPlanning#Hardware_requirements). -* In the following sections, AWS S3 remote bucket is used for placing the splunk apps, but as given in the [app framework doc](https://splunk.github.io/splunk-operator/AppFramework.html), you can use Azure Blob remote buckets also. +* In the following sections, AWS S3 remote bucket is used for placing the splunk apps, but as given in the [app framework doc](/configuration/AppFramework), you can use Azure Blob remote buckets also. * You need to deploy add-ons to forwarders manually (or through your own methods). * You need to deploy Stream App manually * For ES version 7.1 or higher, [Behavioral Analytics Service](https://docs.splunk.com/Documentation/ES/7.1.0/User/BehavioralAnalyticsIntro#Provision_behavioral_analytics_service_with_Splunk_Enterprise_Security_7.1.0_or_higher) is unavailable for containerized Splunk deployments (supported for cloud releases only) @@ -46,7 +52,7 @@ When installing ES in an indexer clustering environment through the Splunk Opera When crafting your Custom Resource(CR) to create a Splunk Enterprise Deployment it is necessary to take the following configurations into account. -##### [appSources](https://splunk.github.io/splunk-operator/AppFramework.html#appsources) scope +##### [appSources](/configuration/AppFramework) scope - When deploying ES to a Standalone or to a Search Head Cluster, it must be configured with an appSources scope of "premiumApps". - When deploying the Splunk_TA_ForIndexers app to an Indexer Cluster, it must be configured with an appSources scope of "cluster". @@ -357,5 +363,5 @@ Check the pod log (e.g deployer pod) in case you want to monitor the pod while i Common issues that may be encountered are : * ES installation failed as you used default sslEnablement mode ("strict") - enable Splunk Web SSL in web.conf. See the section [Special consideration while using ssl enabled mode of strict in SHC](#special-consideration-while-using-ssl-enabled-mode-of-strict-in-shc) * Ansible task timeouts - raise associated timeout (splunkdConnectionTimeout in web.conf, rcv_timeout, send_timeeout, cxn_timeeout etc values in server.conf) -* Pod Recycles - raise livenessProbe value. More details on this at [Health Check doc](HealthCheck.md) +* Pod Recycles - raise livenessProbe value. More details on this at [Health Check doc](/troubleshooting/HealthCheck) diff --git a/docs/Security.md b/docs/_configuration/Security.md similarity index 94% rename from docs/Security.md rename to docs/_configuration/Security.md index 8fdd85210..e95f92c10 100644 --- a/docs/Security.md +++ b/docs/_configuration/Security.md @@ -1,3 +1,9 @@ +--- +title: Secure Splunk deployments +nav_order: 27 +#nav_exclude: true +--- + # Secure Splunk deployments in Kubernetes Before creating new deployments in Kubernetes, it is important you consider the security aspects of your environment. This document describes how to secure your deployment using the Operator and Splunk Enterprise configurations, and provides examples for some common scenarios. @@ -19,7 +25,7 @@ The procedures to secure your deployment are the same regardless of your choice |Splunk Web | Gateway Termination | NO | |REST API | Gateway Termination | NO | -For more information about how to setup Ingress Controllers using the Operator visit [Ingress Documentation](https://github.com/splunk/splunk-operator/blob/develop/docs/Ingress.md). +For more information about how to setup Ingress Controllers using the Operator visit [Ingress Documentation](/configuration/Ingress). ## Prerequisites @@ -74,7 +80,7 @@ privKeyPath = $SPLUNK_HOME/etc/apps/myapp/mycerts/mySplunkPrivateKey.key serverCert = $SPLUNK_HOME/etc/apps/myapp/mycerts/mySplunkCertificate.pem ``` -* Deploy the app to the Splunk Enterprise instance. See [Install Apps using Splunk Operator](https://github.com/splunk/splunk-operator/blob/develop/docs/Examples.md#installing-splunk-apps). +* Deploy the app to the Splunk Enterprise instance. See [Install Apps using Splunk Operator](/configuration/Examples#installing-splunk-apps). * Create the Ingress configuration to allow access to port 8000. This configuration creates a gateway and virtual service for passing the traffic through to the Splunk Enterprise instance. @@ -219,9 +225,9 @@ Learn more about APIs available here: [REST Manual](https://docs.splunk.com/Docu ## Securing Forwarders -For examples on configuring the Ingress controller to accept data from Forwarders, and securing the data in Kubernetes, see: [Secure Forwarding](https://github.com/splunk/splunk-operator/blob/develop/docs/Ingress.md) +For examples on configuring the Ingress controller to accept data from Forwarders, and securing the data in Kubernetes, see: [Secure Forwarding](/configuration/Ingress) ## Password Management -In Kubernetes, sensitive information such as passwords, OAuth tokens, and ssh keys should be stored using the Secrets objects. Learn how to manage your passwords for Splunk Enterprise deployments in: [Password Management](https://github.com/splunk/splunk-operator/blob/develop/docs/PasswordManagement.md) +In Kubernetes, sensitive information such as passwords, OAuth tokens, and ssh keys should be stored using the Secrets objects. Learn how to manage your passwords for Splunk Enterprise deployments in: [Password Management](/configuration/PasswordManagement) diff --git a/docs/SmartStore.md b/docs/_configuration/SmartStore.md similarity index 60% rename from docs/SmartStore.md rename to docs/_configuration/SmartStore.md index c36944540..eda664015 100644 --- a/docs/SmartStore.md +++ b/docs/_configuration/SmartStore.md @@ -1,8 +1,15 @@ +--- +title: SmartStore +nav_order: 24 +#nav_exclude: true +--- + # SmartStore Resource Guide -*NOTE: The below method is a temporary way of installing SmartStore configuration & indexes. Starting from the Splunk Operator release 1.0.2, an enhanced App installation framework is introduced which is the recommended method to install SmartStore indexes & configuration. The below method may still be used to specify the S3 access keys, which avoids storing them in the S3 buckets (via the App installation framework)* +{: .note } +The below method is a temporary way of installing SmartStore configuration & indexes. Starting from the Splunk Operator release 1.0.2, an enhanced App installation framework is introduced which is the recommended method to install SmartStore indexes & configuration. The below method may still be used to specify the S3 access keys, which avoids storing them in the S3 buckets (via the App installation framework) -The Splunk Operator includes a method for configuring a SmartStore remote storage volume with index support using a [Custom Resource](https://splunk.github.io/splunk-operator/CustomResources.html). The SmartStore integration is not implemented as a StorageClass. This feature and its settings rely on support integrated into Splunk Enterprise. See [SmartStore](https://docs.splunk.com/Documentation/Splunk/latest/Indexer/AboutSmartStore) for information on the feature and implementation considerations. +The Splunk Operator includes a method for configuring a SmartStore remote storage volume with index support using a [Custom Resource](/configuration/CustomResources). The SmartStore integration is not implemented as a StorageClass. This feature and its settings rely on support integrated into Splunk Enterprise. See [SmartStore](https://docs.splunk.com/Documentation/Splunk/latest/Indexer/AboutSmartStore) for information on the feature and implementation considerations. * SmartStore configuration is supported on these Custom Resources: Standalone and ClusterManager. * SmartStore support in the Splunk Operator is limited to Amazon S3 & S3-API-compliant object stores only if you are using the CRD configuration for S3 as described below." @@ -64,7 +71,8 @@ spec: The SmartStore parameters will be placed into the required .conf files in an app. The app is named as `splunk-operator`. In the case of a standalone deployment, the app is located at `/opt/splunk/etc/apps/` -Note: Custom apps with higher precedence can potentially overwrite the index and volume configuration in the splunk-operator app. Hence, care should be taken to avoid conflicting SmartStore configuration in custom apps. See [Configuration file precedence order](https://docs.splunk.com/Documentation/Splunk/latest/Admin/Wheretofindtheconfigurationfiles#How_Splunk_determines_precedence_order) +{: .note } +Custom apps with higher precedence can potentially overwrite the index and volume configuration in the splunk-operator app. Hence, care should be taken to avoid conflicting SmartStore configuration in custom apps. See [Configuration file precedence order](https://docs.splunk.com/Documentation/Splunk/latest/Admin/Wheretofindtheconfigurationfiles#How_Splunk_determines_precedence_order) @@ -76,7 +84,7 @@ Note: Custom apps with higher precedence can potentially overwrite the index and 3. Confirm the name of the Splunk indexes being used with the SmartStore volume. 4. Create/Update the Cluster Manager custom resource specification with volume and index configuration (see Example below) 5. Apply the custom resource specification: kubectl -f apply Clustermanager.yaml -6. Follow the rest of the steps to Create an Indexer Cluster. See [Examples](Examples.md) +6. Follow the rest of the steps to Create an Indexer Cluster. See [Example Deployments](/configuration/Examples) Example. Clustermanager.yaml: @@ -111,127 +119,12 @@ spec: The SmartStore parameters will be placed into the required .conf files in an app. The app is named as `splunk-operator`. In case of a Indexer cluster deployment, the app is located on Cluster manager at `/opt/splunk/etc/manager-apps/`. Once the SmartStore configuration is populated to Cluster Manager's `splunk-operator` app, Operator issues a bundle push command to Cluster Manager, so that the SmartStore configuration is distributed to all the peers in that indexer cluster -Note: Custom apps with higher precedence can potentially overwrite the index and volume configuration in the splunk-operator app. Hence, care should be taken to avoid conflicting SmartStore configuration in custom apps. See [Configuration file precedence order](https://docs.splunk.com/Documentation/Splunk/latest/Admin/Wheretofindtheconfigurationfiles#How_Splunk_determines_precedence_order) +{: .note } +Custom apps with higher precedence can potentially overwrite the index and volume configuration in the splunk-operator app. Hence, care should be taken to avoid conflicting SmartStore configuration in custom apps. See [Configuration file precedence order](https://docs.splunk.com/Documentation/Splunk/latest/Admin/Wheretofindtheconfigurationfiles#How_Splunk_determines_precedence_order) ## SmartStore Resource Spec Parameters -There are additional SmartStore settings available for tuning and storage management. The settings are equivalent to the SmartStore settings defined in indexes.conf and server.conf for Splunk Enterprise. The SmartStore resource applies to the `Standalone` and `ClusterManager` Custom Resources, and adds the following `Spec` configuration parameters: - - -```yaml -smartstore: - description: - Splunk Smartstore configuration. Refer to indexes.conf.spec and - server.conf.spec on docs.splunk.com - properties: - cacheManager: - description: Defines Cache manager settings - properties: - evictionPadding: - description: Additional size beyond 'minFreeSize' before eviction kicks in - type: integer - evictionPolicy: - description: Eviction policy to use - type: string - hotlistBloomFilterRecencyHours: - description: - Time period relative to the bucket's age, during which the bloom - filter file is protected from cache eviction - type: integer - hotlistRecencySecs: - description: - Time period relative to the bucket's age, during which the bucket is - protected from cache eviction - type: integer - maxCacheSize: - description: Max cache size per partition - type: integer - maxConcurrentDownloads: - description: - Maximum number of buckets that can be downloaded from remote storage - in parallel - type: integer - maxConcurrentUploads: - description: - Maximum number of buckets that can be uploaded to remote storage in - parallel - type: integer - type: object - defaults: - description: Default configuration for indexes - properties: - maxGlobalDataSizeMB: - description: - MaxGlobalDataSizeMB defines the maximum amount of space for warm and - cold buckets of an index - type: integer - maxGlobalRawDataSizeMB: - description: - MaxGlobalDataSizeMB defines the maximum amount of cumulative space - for warm and cold buckets of an index - type: integer - volumeName: - description: Remote Volume name - type: string - type: object - indexes: - description: List of Splunk indexes - items: - description: IndexSpec defines Splunk index name and storage path - properties: - hotlistBloomFilterRecencyHours: - description: - Time period relative to the bucket's age, during which the bloom - filter file is protected from cache eviction - type: integer - hotlistRecencySecs: - description: - Time period relative to the bucket's age, during which the bucket - is protected from cache eviction - type: integer - maxGlobalDataSizeMB: - description: - MaxGlobalDataSizeMB defines the maximum amount of space for warm - and cold buckets of an index - type: integer - maxGlobalRawDataSizeMB: - description: - MaxGlobalDataSizeMB defines the maximum amount of cumulative space - for warm and cold buckets of an index - type: integer - name: - description: Splunk index name - type: string - remotePath: - description: Index location relative to the remote volume path - type: string - volumeName: - description: Remote Volume name - type: string - type: object - type: array - volumes: - description: List of remote storage volumes - items: - description: VolumeSpec defines remote volume name and remote volume URI - properties: - endpoint: - description: Remote volume URI - type: string - name: - description: Remote volume name - type: string - path: - description: Remote volume path - type: string - secretRef: - description: Secret object name - type: string - type: object - type: array - type: object - -``` +There are additional SmartStore settings available for tuning and storage management. The settings are equivalent to the SmartStore settings defined in indexes.conf and server.conf for Splunk Enterprise. The SmartStore resource applies to the `Standalone` and `ClusterManager` Custom Resources. Refer to [Custom Resources Reference](/configuration/CustomResources#smartstore-resource-spec-parameters) for all settings. ## Following is the table that maps the Custom Resource SmartStore spec to the Splunk docs. @@ -247,11 +140,11 @@ See [indexes.conf](https://docs.splunk.com/Documentation/Splunk/latest/Admin/Ind | hotlistBloomFilterRecencyHours |hotlist_bloom_filter_recency_hours | [\], [cachemanager] | | endpoint |remote.s3.endpoint | [volume:\] | | path | path | [volume:\] | -| maxConcurrentUploads | max_concurrent_uploads |[cachemanager] | +| maxConcurrentUploads | max_concurrent_uploads | [cachemanager] | | maxConcurrentDownloads | max_concurrent_downloads |[cachemanager] | | maxCacheSize | max_cache_size | [cachemanager] | -| evictionPolicy |eviction_policy |[cachemanager] | -| evictionPadding | eviction_padding |[cachemanager] | +| evictionPolicy |eviction_policy | [cachemanager] | +| evictionPadding | eviction_padding | [cachemanager] | ## Additional configuration @@ -260,12 +153,12 @@ If there is a need to configure additional settings, this can be achieved by con 1. Create an App with the additional configuration For example, in order to set the remote S3 encryption scheme as `sse-s3`, create an app with the config in indexes.conf file under default/local sub-directory as follows: ``` -[volume:\]] +[volume:\] path = remote.s3.encryption = sse-s3 ``` 2. Apply the CR with the necessary & supported Smartstore and Index related configs -3. Install the App created using the [currently supported methods](https://splunk.github.io/splunk-operator/Examples.html#installing-splunk-apps) (*Note: This can be combined with the previous step*) +3. Install the App created using the [currently supported methods](/configuration/Examples#installing-splunk-apps) (*Note: This can be combined with the previous step*) ## RepFactor for Internal Indexes diff --git a/docs/StorageClass.md b/docs/_configuration/StorageClass.md similarity index 95% rename from docs/StorageClass.md rename to docs/_configuration/StorageClass.md index e5ae026e6..551bae5a7 100644 --- a/docs/StorageClass.md +++ b/docs/_configuration/StorageClass.md @@ -1,3 +1,10 @@ +--- +title: Persistent Storage +nav_order: 23 +#nav_exclude: true +--- + + # Setting Up a Persistent Storage for Splunk The Splunk Operator for Kubernetes uses Kubernetes [Storage Classes](https://kubernetes.io/docs/concepts/storage/storage-classes/) to create and manage two Persistent Volumes for all of the Splunk Enterprise pods in your deployment. Two volumes will be mounted for each pod: @@ -121,3 +128,7 @@ We have tested basic functionality of the Splunk Operator with the storage optio * [Rook Ceph](https://www.rook.io/) (open source) But we cannot make any specific recommendations, or verify any claims or comparisons regarding performance. + + +## Workload Management(WLM) Support +Workload management is a rule-based framework that lets you allocate compute and memory resources to search, indexing, and other workloads in Splunk Enterprise. Currently, Splunk Operator deployed workloads do not support this feature. \ No newline at end of file diff --git a/docs/Telemetry.md b/docs/_configuration/Telemetry.md similarity index 94% rename from docs/Telemetry.md rename to docs/_configuration/Telemetry.md index ba53ba7c9..b7efb2350 100644 --- a/docs/Telemetry.md +++ b/docs/_configuration/Telemetry.md @@ -1,3 +1,9 @@ +--- +title: Splunk Operator Telemetry +nav_order: 30 +#nav_exclude: true +--- + # Splunk Operator Telemetry A telemetry solution to collect data from the Splunk Enterprise instances deployed using the Splunk Operator for Kubernetes(SOK) is implemented. The operator installs an app called `app_tel_for_sok8s_` into [primary Splunk Instances](https://docs.splunk.com/Documentation/Splunk/latest/Admin/Shareperformancedata#Which_instance_runs_the_searches_and_sends_data_to_Splunk). The newly installed app's data will be exported as a part of [Splunk Enterprise telemetry solution](https://docs.splunk.com/Documentation/Splunk/latest/Admin/Shareperformancedata) to the telemetry prod servers. The exported telemetry data will help understand number and kind of Splunk deployments using SOK. diff --git a/docs/artifacthub-repo.yml b/docs/_helm/artifacthub-repo.yml similarity index 100% rename from docs/artifacthub-repo.yml rename to docs/_helm/artifacthub-repo.yml diff --git a/docs/_helm/cr.yaml b/docs/_helm/cr.yaml new file mode 100644 index 000000000..88af25978 --- /dev/null +++ b/docs/_helm/cr.yaml @@ -0,0 +1,2 @@ +pages-branch: jekyll-docs #main +pages-index-path: docs/_helm/index.yaml \ No newline at end of file diff --git a/docs/index.yaml b/docs/_helm/index.yaml similarity index 74% rename from docs/index.yaml rename to docs/_helm/index.yaml index d15a698b5..da55e317a 100644 --- a/docs/index.yaml +++ b/docs/_helm/index.yaml @@ -1,9 +1,29 @@ apiVersion: v1 entries: splunk-enterprise: + - apiVersion: v2 + appVersion: 2.5.0 + created: "2024-01-22T12:51:00.460454-08:00" + dependencies: + - condition: splunk-operator.enabled + name: splunk-operator + repository: file://splunk-operator/helm-chart/splunk-operator + version: 2.5.0 + description: A Helm chart for Splunk Enterprise managed by the Splunk Operator + digest: e9510495e61e31c9f0b6cc7f4e0c9a1bdf17a7772ab881df13abd9903c46f556 + maintainers: + - email: vivekr@splunk.com + name: Vivek Reddy + - email: akondur@splunk.com + name: Arjun Kondur + name: splunk-enterprise + type: application + urls: + - https://splunk.github.io/splunk-operator/splunk-enterprise-2.5.0.tgz + version: 2.5.0 - apiVersion: v2 appVersion: 2.4.0 - created: "2023-10-06T15:35:58.241056-07:00" + created: "2024-01-22T12:51:00.419046-08:00" dependencies: - condition: splunk-operator.enabled name: splunk-operator @@ -25,7 +45,7 @@ entries: version: 2.4.0 - apiVersion: v2 appVersion: 2.3.0 - created: "2023-10-06T15:35:58.21754-07:00" + created: "2024-01-22T12:51:00.387561-08:00" dependencies: - condition: splunk-operator.enabled name: splunk-operator @@ -47,7 +67,7 @@ entries: version: 2.3.0 - apiVersion: v2 appVersion: 2.2.1 - created: "2023-10-06T15:35:58.202704-07:00" + created: "2024-01-22T12:51:00.373328-08:00" dependencies: - condition: splunk-operator.enabled name: splunk-operator @@ -62,7 +82,7 @@ entries: version: 2.2.1 - apiVersion: v2 appVersion: 2.2.0 - created: "2023-10-06T15:35:58.187926-07:00" + created: "2024-01-22T12:51:00.357163-08:00" dependencies: - condition: splunk-operator.enabled name: splunk-operator @@ -77,7 +97,7 @@ entries: version: 2.2.0 - apiVersion: v2 appVersion: 2.1.0 - created: "2023-10-06T15:35:58.162232-07:00" + created: "2024-01-22T12:51:00.330725-08:00" dependencies: - condition: splunk-operator.enabled name: splunk-operator @@ -91,9 +111,24 @@ entries: - https://splunk.github.io/splunk-operator/splunk-enterprise-1.0.0.tgz version: 1.0.0 splunk-operator: + - apiVersion: v2 + appVersion: 2.5.0 + created: "2024-01-22T12:51:00.541778-08:00" + description: A Helm chart for the Splunk Operator for Kubernetes + digest: ed93f8fac421f92cfdbfd043ec27911a07ec7db2c05b4efc3137cef4f2bfca4a + maintainers: + - email: vivekr@splunk.com + name: Vivek Reddy + - email: akondur@splunk.com + name: Arjun Kondur + name: splunk-operator + type: application + urls: + - https://splunk.github.io/splunk-operator/splunk-operator-2.5.0.tgz + version: 2.5.0 - apiVersion: v2 appVersion: 2.4.0 - created: "2023-10-06T15:35:58.303657-07:00" + created: "2024-01-22T12:51:00.527611-08:00" description: A Helm chart for the Splunk Operator for Kubernetes digest: 9d0377747e46df4bf4b9dbd447c9ff46c926bfe2c66fd07d6d27a61abb31cb42 maintainers: @@ -110,7 +145,7 @@ entries: version: 2.4.0 - apiVersion: v2 appVersion: 2.3.0 - created: "2023-10-06T15:35:58.291618-07:00" + created: "2024-01-22T12:51:00.513743-08:00" description: A Helm chart for the Splunk Operator for Kubernetes digest: 23e70ec4059bc92920d7d3adce3bff6b8aba0d5eb5d4c0efe225bf3b88d5b274 maintainers: @@ -127,7 +162,7 @@ entries: version: 2.3.0 - apiVersion: v2 appVersion: 2.2.1 - created: "2023-10-06T15:35:58.278709-07:00" + created: "2024-01-22T12:51:00.500321-08:00" description: A Helm chart for the Splunk Operator for Kubernetes digest: 8868b9ae2ebde0c667b13c97d71d904a31b5a9f2c803b199bc77324f1727e1fd name: splunk-operator @@ -137,7 +172,7 @@ entries: version: 2.2.1 - apiVersion: v2 appVersion: 2.2.0 - created: "2023-10-06T15:35:58.264055-07:00" + created: "2024-01-22T12:51:00.487851-08:00" description: A Helm chart for the Splunk Operator for Kubernetes digest: 49c72276bd7ff93465b0545d8b0814f684cade7d2cd191b6d73d4c3660bd1fb4 name: splunk-operator @@ -147,7 +182,7 @@ entries: version: 2.2.0 - apiVersion: v2 appVersion: 2.1.0 - created: "2023-10-06T15:35:58.252222-07:00" + created: "2024-01-22T12:51:00.473934-08:00" description: A Helm chart for the Splunk Operator for Kubernetes digest: 34e5463f8f5442655d05cb616b50391b738a0827b30d8440b4c7fce99a291d9a name: splunk-operator @@ -155,4 +190,4 @@ entries: urls: - https://splunk.github.io/splunk-operator/splunk-operator-1.0.0.tgz version: 1.0.0 -generated: "2023-10-06T15:35:58.146197-07:00" +generated: "2024-01-22T12:51:00.315345-08:00" diff --git a/docs/splunk-enterprise-1.0.0.tgz b/docs/_helm/splunk-enterprise-1.0.0.tgz similarity index 100% rename from docs/splunk-enterprise-1.0.0.tgz rename to docs/_helm/splunk-enterprise-1.0.0.tgz diff --git a/docs/splunk-enterprise-2.2.0.tgz b/docs/_helm/splunk-enterprise-2.2.0.tgz similarity index 100% rename from docs/splunk-enterprise-2.2.0.tgz rename to docs/_helm/splunk-enterprise-2.2.0.tgz diff --git a/docs/splunk-enterprise-2.2.1.tgz b/docs/_helm/splunk-enterprise-2.2.1.tgz similarity index 100% rename from docs/splunk-enterprise-2.2.1.tgz rename to docs/_helm/splunk-enterprise-2.2.1.tgz diff --git a/docs/splunk-enterprise-2.3.0.tgz b/docs/_helm/splunk-enterprise-2.3.0.tgz similarity index 100% rename from docs/splunk-enterprise-2.3.0.tgz rename to docs/_helm/splunk-enterprise-2.3.0.tgz diff --git a/docs/splunk-enterprise-2.4.0.tgz b/docs/_helm/splunk-enterprise-2.4.0.tgz similarity index 100% rename from docs/splunk-enterprise-2.4.0.tgz rename to docs/_helm/splunk-enterprise-2.4.0.tgz diff --git a/docs/_helm/splunk-enterprise-2.5.0.tgz b/docs/_helm/splunk-enterprise-2.5.0.tgz new file mode 100644 index 000000000..ea469f87e Binary files /dev/null and b/docs/_helm/splunk-enterprise-2.5.0.tgz differ diff --git a/docs/splunk-operator-1.0.0.tgz b/docs/_helm/splunk-operator-1.0.0.tgz similarity index 100% rename from docs/splunk-operator-1.0.0.tgz rename to docs/_helm/splunk-operator-1.0.0.tgz diff --git a/docs/splunk-operator-2.2.0.tgz b/docs/_helm/splunk-operator-2.2.0.tgz similarity index 100% rename from docs/splunk-operator-2.2.0.tgz rename to docs/_helm/splunk-operator-2.2.0.tgz diff --git a/docs/splunk-operator-2.2.1.tgz b/docs/_helm/splunk-operator-2.2.1.tgz similarity index 100% rename from docs/splunk-operator-2.2.1.tgz rename to docs/_helm/splunk-operator-2.2.1.tgz diff --git a/docs/splunk-operator-2.3.0.tgz b/docs/_helm/splunk-operator-2.3.0.tgz similarity index 100% rename from docs/splunk-operator-2.3.0.tgz rename to docs/_helm/splunk-operator-2.3.0.tgz diff --git a/docs/splunk-operator-2.4.0.tgz b/docs/_helm/splunk-operator-2.4.0.tgz similarity index 100% rename from docs/splunk-operator-2.4.0.tgz rename to docs/_helm/splunk-operator-2.4.0.tgz diff --git a/docs/_helm/splunk-operator-2.5.0.tgz b/docs/_helm/splunk-operator-2.5.0.tgz new file mode 100644 index 000000000..0e427094d Binary files /dev/null and b/docs/_helm/splunk-operator-2.5.0.tgz differ diff --git a/docs/_includes/components/site_nav.html b/docs/_includes/components/site_nav.html new file mode 100644 index 000000000..c794d39a5 --- /dev/null +++ b/docs/_includes/components/site_nav.html @@ -0,0 +1,76 @@ +{%- comment -%} + Include as: {%- include_cached components/site_nav.html -%} + Depends on: site. + Results in: HTML for the site-nav. + Includes: + components/nav.html + Overwrites: + pages_top_size, collections_size, collection_entry, + collection_key, collection_value, collection. +{%- endcomment -%} + + \ No newline at end of file diff --git a/docs/Install.md b/docs/_installation/AdvancedInstallation.md similarity index 77% rename from docs/Install.md rename to docs/_installation/AdvancedInstallation.md index 072afbed0..1028add25 100644 --- a/docs/Install.md +++ b/docs/_installation/AdvancedInstallation.md @@ -1,13 +1,17 @@ -# Splunk Operator Advanced Installation - +--- +title: Advanced Installation +nav_order: 12 +#nav_exclude: true +--- +# Splunk Operator Advanced Installation ## Downloading Installation YAML for modifications If you want to customize the installation of the Splunk Operator, download a copy of the installation YAML locally, and open it in your favorite editor. -``` -wget -O splunk-operator-cluster.yaml https://github.com/splunk/splunk-operator/releases/download/2.4.0/splunk-operator-cluster.yaml +```bash +wget -O splunk-operator-cluster.yaml https://github.com/splunk/splunk-operator/releases/download/{{ page.splunk_operator_version }}/splunk-operator-cluster.yaml ``` ## Default Installation @@ -16,8 +20,8 @@ Based on the file used Splunk Operator can be installed cluster-wide or namespac By installing `splunk-operator-cluster.yaml` Operator will watch all the namespaces of your cluster for splunk enterprise custom resources -``` -wget -O splunk-operator-cluster.yaml https://github.com/splunk/splunk-operator/releases/download/2.4.0/splunk-operator-cluster.yaml +```bash +wget -O splunk-operator-cluster.yaml https://github.com/splunk/splunk-operator/releases/download/{{ page.splunk_operator_version }}/splunk-operator-cluster.yaml kubectl apply -f splunk-operator-cluster.yaml ``` @@ -31,7 +35,7 @@ If Splunk Operator is installed clusterwide and user wants to manage multiple na - name: WATCH_NAMESPACE value: "namespace1,namespace2" - name: RELATED_IMAGE_SPLUNK_ENTERPRISE - value: splunk/splunk:9.0.3-a2 + value: splunk/splunk:{{ page.splunk_enterprise_version }} - name: OPERATOR_NAME value: splunk-operator - name: POD_NAME @@ -44,10 +48,10 @@ If Splunk Operator is installed clusterwide and user wants to manage multiple na ## Install operator to watch single namespace with restrictive permission -In order to install operator with restrictive permission to watch only single namespace use [splunk-operator-namespace.yaml](https://github.com/splunk/splunk-operator/releases/download/2.4.0/splunk-operator-namespace.yaml). This will create Role and Role-Binding to only watch single namespace. By default operator will be installed in `splunk-operator` namespace, user can edit the file to change the namespace +In order to install operator with restrictive permission to watch only single namespace use [splunk-operator-namespace.yaml](https://github.com/splunk/splunk-operator/releases/download/{{ page.splunk_operator_version }}/splunk-operator-namespace.yaml). This will create Role and Role-Binding to only watch single namespace. By default operator will be installed in `splunk-operator` namespace, user can edit the file to change the namespace -``` -wget -O splunk-operator-namespace.yaml https://github.com/splunk/splunk-operator/releases/download/2.4.0/splunk-operator-namespace.yaml +```bash +wget -O splunk-operator-namespace.yaml https://github.com/splunk/splunk-operator/releases/download/{{ page.splunk_operator_version }}/splunk-operator-namespace.yaml kubectl apply -f splunk-operator-namespace.yaml ``` @@ -68,7 +72,7 @@ If you are using a private registry for the Docker images, edit `deployment` `sp - name: WATCH_NAMESPACE value: "namespace1,namespace2" - name: RELATED_IMAGE_SPLUNK_ENTERPRISE - value: splunk/splunk:9.0.3-a2 + value: splunk/splunk:{{ page.splunk_enterprise_version }} - name: OPERATOR_NAME value: splunk-operator - name: POD_NAME @@ -81,8 +85,7 @@ If you are using a private registry for the Docker images, edit `deployment` `sp ## Cluster Domain -By default, the Splunk Operator will use a Kubernetes cluster domain of `cluster.local` to calculate the fully qualified domain names (FQDN) for each instance in your deployment. If you have configured a custom domain for your Kubernetes cluster, you can override the operator by adding a `CLUSTER_DOMAIN` -environment variable to the operator's deployment spec: +By default, the Splunk Operator will use a Kubernetes cluster domain of `cluster.local` to calculate the fully qualified domain names (FQDN) for each instance in your deployment. If you have configured a custom domain for your Kubernetes cluster, you can override the operator by adding a `CLUSTER_DOMAIN` environment variable to the operator's deployment spec ```yaml - name: CLUSTER_DOMAIN diff --git a/docs/Helm.md b/docs/_installation/Helm.md similarity index 96% rename from docs/Helm.md rename to docs/_installation/Helm.md index 5f19fd46c..c191f45c3 100644 --- a/docs/Helm.md +++ b/docs/_installation/Helm.md @@ -1,3 +1,9 @@ +--- +title: Helm +nav_order: 13 +#nav_exclude: true +--- + # Splunk Operator Helm Installation ## Splunk Operator Helm chart Repository @@ -11,11 +17,12 @@ helm repo update The ```splunk``` chart repository contains the ```splunk/splunk-operator``` chart to deploy the Splunk Operator and the ```splunk/splunk-enterprise``` chart to deploy Splunk Enterprise custom resources. +{: .note } Upgrading to latest version of splunk operator using helm chart will not upgrade CRDs. User need to deploy the latest CRDs manually. this is [limitation](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/) from helm ``` git clone https://github.com/splunk/splunk-operator.git . -git checkout release/2.3.0 +git checkout release/{{ page.operator_release_version }} make install ``` @@ -154,7 +161,8 @@ release "splunk-enterprise-test" uninstalled ``` ```helm uninstall``` terminates all resources deployed by Helm including Persistent Volume Claims created for Splunk Enterprise resources. -Note: Helm by default does not cleanup Custom Resource Definitions and Persistent Volume Claims. Splunk Admin needs to manually clean them. +{: .note } +Helm by default does not cleanup Custom Resource Definitions and Persistent Volume Claims. Splunk Admin needs to manually clean them. ## Splunk Validated Architecture deployments diff --git a/docs/Images.md b/docs/_installation/Images.md similarity index 94% rename from docs/Images.md rename to docs/_installation/Images.md index 41281ace3..3e5f3282b 100644 --- a/docs/Images.md +++ b/docs/_installation/Images.md @@ -1,3 +1,9 @@ +--- +title: Docker Images +nav_order: 14 +#nav_exclude: true +--- + # Required Docker Images The Splunk Operator requires these docker images to be present or available to your Kubernetes cluster: @@ -12,7 +18,7 @@ custom resource definition. Use the `RELATED_IMAGE_SPLUNK_ENTERPRISE` environment variable or the `image` custom resource parameter to change the location of your Splunk Enterprise image. -For additional detail, see the [Advanced Installation Instructions](Install.md) page, and the [Custom Resource Guide](CustomResources.md) page. +For additional detail, see the [Advanced Installation Instructions](/installation/AdvancedInstallation) page, and the [Custom Resource Reference](/configuration/CustomResources) page. ## Using a private registry diff --git a/docs/OpenShift.md b/docs/_installation/OpenShift.md similarity index 96% rename from docs/OpenShift.md rename to docs/_installation/OpenShift.md index b8c1aab8e..65275d7dc 100644 --- a/docs/OpenShift.md +++ b/docs/_installation/OpenShift.md @@ -1,3 +1,8 @@ +--- +title: Red Hat OpenShift +nav_order: 15 +--- + # Red Hat OpenShift Configuration The Splunk Operator will always start Splunk Enterprise containers using diff --git a/docs/_installation/Prerequisites.md b/docs/_installation/Prerequisites.md new file mode 100644 index 000000000..66faa5117 --- /dev/null +++ b/docs/_installation/Prerequisites.md @@ -0,0 +1,51 @@ +--- +title: Prerequisites +nav_order: 11 +--- + +## Prerequisites +- Version >=1.5.0 of the Splunk Operator requires a Kubernetes cluster of version >=1.26.0. +- The Splunk Operator requires SmartStore to be configurted for indexed data storage. +- The use of Persistent Volume Claims requires that your cluster is configured to support one or more Kubernetes persistent Storage Classes + + +### Kubernetes Platform recommendations + +The Splunk Operator should work with any [CNCF certified distribution](https://www.cncf.io/certification/software-conformance/) of Kubernetes. We do not have platform recommendations, but this is a table of platforms that our developers, customers, and partners have used successfully with the Splunk Operator. + + + + + + +
Splunk Development & Testing Platforms Amazon Elastic Kubernetes Service (EKS), Google Kubernetes Engine (GKE)
Customer Reported Platforms Microsoft Azure Kubernetes Service (AKS), Red Hat OpenShift
Partner Tested Platforms HPE Ezmeral
Other Platforms CNCF certified distribution
+ +### Splunk Enterprise Version Compatibility + +Each Splunk Operator release has specific Splunk Enterprise compatibility requirements. Splunk Operator can support more than one version of Splunk Enterprise release. Before installing or upgrading the Splunk Operator, review the [release notes](https://github.com/splunk/splunk-operator/releases) to verify version compatibility with Splunk Enterprise releases. + + +### Hardware Resources Requirements +The resource guidelines for running production Splunk Enterprise instances in pods through the Splunk Operator are the same as running Splunk Enterprise natively on a supported operating system and file system. Refer to the Splunk Enterprise [Reference Hardware documentation](https://docs.splunk.com/Documentation/Splunk/latest/Capacity/Referencehardware) for additional details. We would also recommend following the same guidance on [Splunk Enterprise for disabling Transparent Huge Pages (THP)](https://docs.splunk.com/Documentation/Splunk/latest/ReleaseNotes/SplunkandTHP) for the nodes in your Kubernetes cluster. Please be aware that this may impact performance of other non-Splunk workloads. + + +#### Minimum Reference Hardware +Based on Splunk Enterprise [Reference Hardware documentation](https://docs.splunk.com/Documentation/Splunk/latest/Capacity/Referencehardware), a summary of the minimum reference hardware requirements is given below. + +| Standalone | Search Head / Search Head Cluster | Indexer Cluster | +| ---------- | ------- | ------- | +| _Each Standalone Pod: 12 Physical CPU Cores or 24 vCPU at 2Ghz or greater per core, 12GB RAM._| _Each Search Head Pod: 16 Physical CPU Cores or 32 vCPU at 2Ghz or greater per core, 12GB RAM._| _Each Indexer Pod: 12 Physical CPU cores, or 24 vCPU at 2GHz or greater per core, 12GB RAM._ | + + +### Storage guidelines +The Splunk Operator uses Kubernetes [Persistent Volume Claims](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) to store all of your Splunk Enterprise configuration ("$SPLUNK_HOME/etc" path) and event ("$SPLUNK_HOME/var" path) data. If one of the underlying machines fail, Kubernetes will automatically try to recover by restarting the Splunk Enterprise pods on another machine that is able to reuse the same data volumes. This minimizes the maintenance burden on your operations team by reducing the impact of common hardware failures to the equivalent of a service restart. +The use of Persistent Volume Claims requires that your cluster is configured to support one or more Kubernetes persistent [Storage Classes](https://kubernetes.io/docs/concepts/storage/storage-classes/). See the [Setting Up a Persistent Storage for Splunk](/configuration/StorageClass) page for more +information. + +### What Storage Type To Use? + +The Kubernetes infrastructure must have access to storage that meets or exceeds the recommendations provided in the Splunk Enterprise storage type recommendations at [Reference Hardware documentation - what storage type to use for a given role?](https://docs.splunk.com/Documentation/Splunk/latest/Capacity/Referencehardware#What_storage_type_should_I_use_for_a_role.3F) In summary, Indexers with SmartStore need NVMe or SSD storage to provide the necessary IOPs for a successful Splunk Enterprise environment. + + +### Splunk SmartStore Required +For production environments, we are requiring the use of Splunk SmartStore. As a Splunk Enterprise deployment's data volume increases, demand for storage typically outpaces demand for compute resources. [Splunk's SmartStore Feature](https://docs.splunk.com/Documentation/Splunk/latest/Indexer/AboutSmartStore) allows you to manage your indexer storage and compute resources in a ___cost-effective___ manner by scaling those resources separately. SmartStore utilizes a fast storage cache on each indexer node to keep recent data locally available for search and keep other data in a remote object store. Look into the [SmartStore Resource Guide](/configuration/SmartStore) document for configuring and using SmartStore through operator. diff --git a/docs/SplunkOperatorUpgrade.md b/docs/_installation/SplunkOperatorUpgrade.md similarity index 80% rename from docs/SplunkOperatorUpgrade.md rename to docs/_installation/SplunkOperatorUpgrade.md index db2b18f73..1c6a77aa4 100644 --- a/docs/SplunkOperatorUpgrade.md +++ b/docs/_installation/SplunkOperatorUpgrade.md @@ -1,6 +1,11 @@ +--- +title: Upgrade Splunk Operator +nav_order: 16 +--- + # How to upgrade Splunk Operator and Splunk Enterprise Deployments -To upgrade the Splunk Operator for Kubernetes, you will overwrite the prior Operator release with the latest version. Once the lastest version of `splunk-operator-namespace.yaml` ([see below](#upgrading-splunk-operator-and-splunk-operator-deployment)) is applied the CRD's are updated and Operator deployment is updated with newer version of Splunk Operator image. Any new spec defined by the operator will be applied to the pods managed by Splunk Operator for Kubernetes. +To upgrade the Splunk Operator for Kubernetes, you will overwrite the prior Operator release with the latest version. Once the lastest version of `splunk-operator-namespace.yaml` ([see below](#upgrading-splunk-operator-and-splunk-operator-deployment)) is applied the CRD's are updated and Operator deployment is updated with newer version of Splunk Operator image. Any new spec defined by the operator will be applied to the pods managed by Splunk Operator for Kubernetes. ​ A Splunk Operator for Kubernetes upgrade might include support for a later version of the Splunk Enterprise Docker image. In that scenario, after the Splunk Operator completes its upgrade, the pods managed by Splunk Operator for Kubernetes will be restarted using the latest Splunk Enterprise Docker image. ​ @@ -10,7 +15,7 @@ A Splunk Operator for Kubernetes upgrade might include support for a later versi ​ * Before you upgrade, review the Splunk Operator [change log](https://github.com/splunk/splunk-operator/releases) page for information on changes made in the latest release. The Splunk Enterprise Docker image compatibility is noted in each release version. ​ -* If the Splunk Enterprise Docker image changes, review the Splunk Enterprise [Upgrade Readme](https://docs.splunk.com/Documentation/Splunk/latest/Installation/AboutupgradingREADTHISFIRST) page before upgrading. +* If the Splunk Enterprise Docker image changes, review the Splunk Enterprise [Upgrade Readme](https://docs.splunk.com/Documentation/Splunk/latest/Installation/AboutupgradingREADTHISFIRST) page before upgrading. ​ * For general information about Splunk Enterprise compatibility and the upgrade process, see [How to upgrade Splunk Enterprise](https://docs.splunk.com/Documentation/Splunk/latest/Installation/HowtoupgradeSplunk). ​ @@ -25,7 +30,7 @@ A Splunk Operator for Kubernetes upgrade might include support for a later versi 1. Download the latest Splunk Operator installation yaml file. ​ ``` -wget -O splunk-operator-namespace.yaml https://github.com/splunk/splunk-operator/releases/download/2.4.0/splunk-operator-namespace.yaml +wget -O splunk-operator-namespace.yaml https://github.com/splunk/splunk-operator/releases/download/2.5.0/splunk-operator-namespace.yaml ``` ​ 2. (Optional) Review the file and update it with your specific customizations used during your install. @@ -44,9 +49,12 @@ NAME READY STATUS RESTARTS splunk-operator-controller-manager-75f5d4d85b-8pshn 1/1 Running 0 5s ``` ​ -If a Splunk Operator release changes the custom resource (CRD) API version, the administrator is responsible for updating their Custom Resource specification to reference the latest CRD API version. -​ -If a Splunk Operator release includes an updated Splunk Enterprise Docker image, the operator upgrade will also initiate pod restart using the latest Splunk Enterprise Docker image. +If a Splunk Operator release changes the custom resource (CRD) API version, the administrator is responsible for updating their Custom Resource specification to reference the latest CRD API version. + +### Upgrading Splunk Enterprise Docker Image with the Operator Upgrade + +Splunk Operator follows the upgrade path steps mentioned in [Splunk documentation](https://docs.splunk.com/Documentation/Splunk/9.1.2/Installation/HowtoupgradeSplunk). If a Splunk Operator release includes an updated Splunk Enterprise Docker image, the operator upgrade will also initiate pod restart using the latest Splunk Enterprise Docker image. To follow the best practices described under the [General Process to Upgrade the Splunk Enterprise], a recommeded upgrade path is followed while initiating pod restarts of different Splunk Instances. At each step, if a particular CR instance exists, a certain flow is imposed to ensure that each instance is updated in the correct order. After an instance is upgraded, the Operator verifies if the upgrade was successful and all the components are working as expected. If any unexpected behaviour is detected, the process is terminated. + ## Steps to Upgrade from 1.0.5 or older version to latest @@ -128,7 +136,7 @@ imagePullPolicy: IfNotPresent ```bash kubectl get pod -o yaml | grep -i image image: docker.io/splunk/splunk-operator: -imagePullPolicy: IfNotPresent +imagePullPolicy: IfNotPresent ``` ​ To verify that a new Splunk Enterprise Docker image was applied to a pod, you can check the version of the image. Example: @@ -143,8 +151,10 @@ imagePullPolicy: IfNotPresent This is an example of the process followed by the Splunk Operator if the operator version is upgraded and a later Splunk Enterprise Docker image is available: ​ 1. A new Splunk Operator pod will be created, and the existing operator pod will be terminated. -2. Any existing License Manager, Search Head, Deployer, ClusterManager, Standalone pods will be terminated to be redeployed with the upgraded spec. -3. After a ClusterManager pod is restarted, the Indexer Cluster pods which are connected to it are terminated and redeployed. -4. After all pods in the Indexer cluster and Search head cluster are redeployed, the Monitoring Console pod is terminated and redeployed. +3. Any existing License Manager, Standalone, Monitoring console, Cluster manager, Search Head, ClusterManager, Indexer pods will be terminated to be redeployed with the upgraded spec. +4. Splunk Operator follows the upgrade path steps mentioned in Splunk documentation. The termination and redeployment of the pods happen in a particular order based on a recommended upgrade path. +5. After a ClusterManager pod is restarted, the Indexer Cluster pods which are connected to it are terminated and redeployed. +6. After all pods in the Indexer cluster and Search head cluster are redeployed, the Monitoring Console pod is terminated and redeployed. +7. Each pod upgrade is verified to ensure the process was successful and everything is working as expected. * Note: If there are multiple pods per Custom Resource, the pods are terminated and re-deployed in a descending order with the highest numbered pod going first diff --git a/docs/_sass/custom/custom.scss b/docs/_sass/custom/custom.scss new file mode 100644 index 000000000..685551ad3 --- /dev/null +++ b/docs/_sass/custom/custom.scss @@ -0,0 +1,4 @@ +.nav-category-divider { + padding: $sp-1; + // border-top: $border $border-color; + } \ No newline at end of file diff --git a/docs/HealthCheck.md b/docs/_troubleshooting/HealthCheck.md similarity index 96% rename from docs/HealthCheck.md rename to docs/_troubleshooting/HealthCheck.md index 19b8fff2d..8622754aa 100644 --- a/docs/HealthCheck.md +++ b/docs/_troubleshooting/HealthCheck.md @@ -1,3 +1,9 @@ +--- +title: Health Checks +nav_order: 51 +#nav_exclude: true +--- + # Splunk Operator Health Check with K8 Probes Splunk Operator supports Startup, Liveness and Readiness Probes (with its own default values) for Splunk Custom Resources. The following probe configurations are allowed to be modified through Custom Resources: * initialDelaySeconds diff --git a/docs/K8SCollectors.md b/docs/_troubleshooting/K8SCollectors.md similarity index 99% rename from docs/K8SCollectors.md rename to docs/_troubleshooting/K8SCollectors.md index 36c7f5269..11dbc7320 100755 --- a/docs/K8SCollectors.md +++ b/docs/_troubleshooting/K8SCollectors.md @@ -1,3 +1,9 @@ +--- +title: K8s Data Collectors +nav_order: 52 +#nav_exclude: true +--- + # **K8s data collectors** The Splunk Operator for K8s deploys Splunk Enterprise custom resources across a single namespace or multiple namespaces. The helper scripts `k8s-splunk-collector.sh` and `k8s-systeminfo-collector.sh` in the [tools directory](https://github.com/splunk/splunk-operator/tree/main/tools/k8s_collectors) collect data from a K8s cluster which runs the Splunk Operator for K8s. diff --git a/docs/pictures/TLS-End-to-End.png b/docs/assets/images/TLS-End-to-End.png similarity index 100% rename from docs/pictures/TLS-End-to-End.png rename to docs/assets/images/TLS-End-to-End.png diff --git a/docs/pictures/TLS-Gateway-Termination.png b/docs/assets/images/TLS-Gateway-Termination.png similarity index 100% rename from docs/pictures/TLS-Gateway-Termination.png rename to docs/assets/images/TLS-Gateway-Termination.png diff --git a/docs/assets/images/favicon.ico b/docs/assets/images/favicon.ico new file mode 100644 index 000000000..2eb15640a Binary files /dev/null and b/docs/assets/images/favicon.ico differ diff --git a/docs/cr.yaml b/docs/cr.yaml deleted file mode 100644 index 6892c39fd..000000000 --- a/docs/cr.yaml +++ /dev/null @@ -1,2 +0,0 @@ -pages-branch: main -pages-index-path: docs/index.yaml \ No newline at end of file diff --git a/docs/BiasLanguageMigration.md b/docs/pages/BiasLanguageMigration.md similarity index 96% rename from docs/BiasLanguageMigration.md rename to docs/pages/BiasLanguageMigration.md index 19d54f420..2dfaf90e4 100644 --- a/docs/BiasLanguageMigration.md +++ b/docs/pages/BiasLanguageMigration.md @@ -1,3 +1,11 @@ +--- +title: FAQ - Biased Language Migration +nav_order: 100 +#nav_exclude: true +nav_after_collections: true +permalink: /BiasLanguageMigration +--- + # FAQ - Biased Language Migration @@ -13,7 +21,7 @@ Starting in the Operator version 2.1.0 we are introducing new CRDs for ClusterMa ## Which CRD should I choose for a new deployment? -All new deployments are recommended to use the new ClusterManager and LicenseManager CRDs. The examples in our documentation have been updated to use the new CRDs. Please check [Configuring Splunk Enterprise Deployments](https://github.com/splunk/splunk-operator/blob/master/docs/Examples.md) for details. +All new deployments are recommended to use the new ClusterManager and LicenseManager CRDs. The examples in our documentation have been updated to use the new CRDs. Please check [Example Deployments](/configuration/Examples) for details. ## How to plan for a migration? diff --git a/docs/CONTRIBUTING.md b/docs/pages/CONTRIBUTING.md similarity index 86% rename from docs/CONTRIBUTING.md rename to docs/pages/CONTRIBUTING.md index b1a49db55..00fd9581d 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/pages/CONTRIBUTING.md @@ -1,22 +1,19 @@ +--- +title: Contributing +nav_order: 102 +nav_after_collections: true +permalink: /Contributing +--- + # Contributing to the Project +{: .no_toc } This document is the single source of truth on contributing towards this codebase. Feel free to browse the [open issues](https://github.com/splunk/splunk-operator/issues) and file new ones - all feedback is welcome! -## Navigation - -- [Contributing to the Project](#contributing-to-the-project) - - [Navigation](#navigation) - - [Prerequisites](#prerequisites) - - [Contributor License Agreement](#contributor-license-agreement) - - [Code of Conduct](#code-of-conduct) - - [Contribution Workflow](#contribution-workflow) - - [Bug reports and feature requests](#bug-reports-and-feature-requests) - - [Fixing issues](#fixing-issues) - - [Pull requests](#pull-requests) - - [Code Review](#code-review) - - [Testing](#testing) - - [Documentation](#documentation) - - [Maintainers](#maintainers) +#### Table of contents +{: .no_toc } +- TOC +{:toc} ## Prerequisites When contributing to this repository, first discuss the issue with a [repository maintainer](#maintainers) via GitHub issue, Slack message, or email. @@ -27,7 +24,7 @@ We only accept pull requests submitted from: * Individuals who have signed the [Splunk Contributor License Agreement](https://www.splunk.com/en_us/form/contributions.html) #### Code of Conduct -All contributors are expected to read our [Code of Conduct](contributing/code-of-conduct.md) and observe it in all interactions involving this project. +All contributors are expected to read our [Code of Conduct](/Contributing#code-of-conduct) and observe it in all interactions involving this project. ## Contribution Workflow Help is always welcome! For example, documentation can always use improvement. There's always code that can be clarified, functionality that can be extended, and tests to be added to guarantee behavior. If you see something you think should be fixed, don't be afraid to own it. @@ -90,7 +87,7 @@ A PR is easy to review if you: * Write good commit messages, concise and descriptive. * Break large changes into a logical series of smaller patches. Patches individually make easily understandable changes, and in aggregate, solve a broader issue. -Reviewers are highly encouraged to revisit the [Code of Conduct](contributing/code-of-conduct.md) and must go above and beyond to promote a collaborative, respectful community. +Reviewers are highly encouraged to revisit the [Code of Conduct](/Contributing#code-of-conduct) and must go above and beyond to promote a collaborative, respectful community. When reviewing PRs from others, [The Gentle Art of Patch Review](http://sage.thesharps.us/2014/09/01/the-gentle-art-of-patch-review/) suggests an iterative series of focuses, designed to lead new contributors to positive collaboration without inundating them initially with nuances: * Is the idea behind the contribution sound? diff --git a/docs/ChangeLog.md b/docs/pages/ChangeLog.md similarity index 98% rename from docs/ChangeLog.md rename to docs/pages/ChangeLog.md index 8158453e6..775dd09c1 100644 --- a/docs/ChangeLog.md +++ b/docs/pages/ChangeLog.md @@ -1,5 +1,30 @@ +--- +title: Change Log +nav_order: 101 +nav_after_collections: true +permalink: /ChangeLog +--- + # Splunk Operator for Kubernetes Change Log +## 2.5.0 (2024-02-05) + +CSPL-2155: Support for Level-2 Upgrade Strategy in Splunk Operator + +CSPL-2505: Pod Security standard set to restricted mode + +### Supported Splunk Version +>| Splunk Version| +>| --- | +>| 9.0.8 | +>| 9.1.3 | + +### Supported Kubernetes Version +>| Kubernetes Version| +>| --- | +>| 1.25+ | + + ## 2.4.0 (2023-10-13) * This is the 2.4.0 release. The Splunk Operator for Kubernetes is a supported platform for deploying Splunk Enterprise with the prerequisites and constraints laid out [here](https://github.com/splunk/splunk-operator/blob/main/docs/README.md#prerequisites-for-the-splunk-operator) diff --git a/docs/pages/configuration.md b/docs/pages/configuration.md new file mode 100644 index 000000000..5d6a2eb36 --- /dev/null +++ b/docs/pages/configuration.md @@ -0,0 +1,7 @@ +--- +title: Configuration +has_children: true +has_toc: false +nav_order: 21 +nav_exclude: true +--- \ No newline at end of file diff --git a/docs/pages/index.md b/docs/pages/index.md new file mode 100644 index 000000000..15e76e484 --- /dev/null +++ b/docs/pages/index.md @@ -0,0 +1,110 @@ +--- +layout: home +title: Getting Started +nav_order: 1 +permalink: "/" +--- + +# Getting Started with the Splunk Operator for Kubernetes + +The Splunk Operator for Kubernetes enables you to quickly and easily deploy Splunk Enterprise on your choice of private or public cloud provider. The Operator simplifies scaling and management of Splunk Enterprise by automating administrative workflows using Kubernetes best practices. + +The Splunk Operator runs as a container, and uses the Kubernetes [operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) and [custom resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) objects to create and manage a scalable and sustainable Splunk Enterprise environment. + +This guide is intended to help new users get up and running with the +Splunk Operator for Kubernetes. + + +## Prerequisites for the Splunk Operator + +- [CNCF certified distribution](/installation/Prerequisites#platform-recommendations) +- Kubernetes configured to support one or more Kubernetes persistent Storage Classes + +## Installing the Splunk Operator + +A Kubernetes cluster administrator can install and start the Splunk Operator for specific namespace by running: +``` +kubectl apply -f https://github.com/splunk/splunk-operator/releases/download/{{ page.splunk_operator_version }}/splunk-operator-namespace.yaml --server-side --force-conflicts +``` + +A Kubernetes cluster administrator can install and start the Splunk Operator for cluster-wide by running: +``` +kubectl apply -f https://github.com/splunk/splunk-operator/releases/download/{{ page.splunk_operator_version }}/splunk-operator-cluster.yaml --server-side --force-conflicts +``` + +The [Advanced Installation Instructions](/installation/AdvancedInstallation) page offers guidance for advanced configurations, including the use of private image registries, installation at cluster scope, and installing the Splunk Operator as a user who is not a Kubernetes administrator. Users of Red Hat OpenShift should review the [Red Hat OpenShift](/installation/OpenShift) page. + +{: .note } +We recommended that the Splunk Enterprise Docker image is copied to a private registry, or directly onto your Kubernetes workers before creating large Splunk Enterprise deployments. See the [Required Images Documentation](/installation/Images) page, and the [Advanced Installation Instructions](/installation/AdvancedInstallation) page for guidance on working with copies of the Docker images. + +After the Splunk Operator starts, you'll see a single pod running within your current namespace: +``` +$ kubectl get pods +NAME READY STATUS RESTARTS AGE +splunk-operator-75f5d4d85b-8pshn 1/1 Running 0 5s +``` + +### Installation using Helm charts + +Installing the Splunk Operator using Helm allows you to quickly deploy the operator and Splunk Enterprise in a Kubernetes cluster. The operator and custom resources are easily configurable allowing for advanced installations including support for Splunk Validated Architectures. Helm also provides a number of features to manage the operator and custom resource lifecycle. The [Installation using Helm](/installation/Helm) page will walk you through installing and configuring Splunk Enterprise deployments using Helm charts. + + +## Creating a Splunk Enterprise deployment + +The `Standalone` custom resource is used to create a single instance deployment of Splunk Enterprise. For example: + +1. Run the command to create a deployment named “s1”: + + +```yaml +cat <=1.5.0 of the Splunk Operator requires a Kubernetes cluster of version >=1.26.0. +- The Splunk Operator requires SmartStore to be configurted for indexed data storage. +- The use of Persistent Volume Claims requires that your cluster is configured to support one or more Kubernetes persistent Storage Classes + + +### Kubernetes Platform recommendations + +The Splunk Operator should work with any [CNCF certified distribution](https://www.cncf.io/certification/software-conformance/) of Kubernetes. We do not have platform recommendations, but this is a table of platforms that our developers, customers, and partners have used successfully with the Splunk Operator. + + + + + + +
Splunk Development & Testing Platforms Amazon Elastic Kubernetes Service (EKS), Google Kubernetes Engine (GKE)
Customer Reported Platforms Microsoft Azure Kubernetes Service (AKS), Red Hat OpenShift
Partner Tested Platforms HPE Ezmeral
Other Platforms CNCF certified distribution
+ +### Splunk Enterprise Version Compatibility + +Each Splunk Operator release has specific Splunk Enterprise compatibility requirements. Splunk Operator can support more than one version of Splunk Enterprise release. Before installing or upgrading the Splunk Operator, review the [release notes](https://github.com/splunk/splunk-operator/releases) to verify version compatibility with Splunk Enterprise releases. + + +### Hardware Resources Requirements +The resource guidelines for running production Splunk Enterprise instances in pods through the Splunk Operator are the same as running Splunk Enterprise natively on a supported operating system and file system. Refer to the Splunk Enterprise [Reference Hardware documentation](https://docs.splunk.com/Documentation/Splunk/latest/Capacity/Referencehardware) for additional details. We would also recommend following the same guidance on [Splunk Enterprise for disabling Transparent Huge Pages (THP)](https://docs.splunk.com/Documentation/Splunk/latest/ReleaseNotes/SplunkandTHP) for the nodes in your Kubernetes cluster. Please be aware that this may impact performance of other non-Splunk workloads. + + +#### Minimum Reference Hardware +Based on Splunk Enterprise [Reference Hardware documentation](https://docs.splunk.com/Documentation/Splunk/latest/Capacity/Referencehardware), a summary of the minimum reference hardware requirements is given below. + +| Standalone | Search Head / Search Head Cluster | Indexer Cluster | +| ---------- | ------- | ------- | +| _Each Standalone Pod: 12 Physical CPU Cores or 24 vCPU at 2Ghz or greater per core, 12GB RAM._| _Each Search Head Pod: 16 Physical CPU Cores or 32 vCPU at 2Ghz or greater per core, 12GB RAM._| _Each Indexer Pod: 12 Physical CPU cores, or 24 vCPU at 2GHz or greater per core, 12GB RAM._ | + + +### Storage guidelines +The Splunk Operator uses Kubernetes [Persistent Volume Claims](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) to store all of your Splunk Enterprise configuration ("$SPLUNK_HOME/etc" path) and event ("$SPLUNK_HOME/var" path) data. If one of the underlying machines fail, Kubernetes will automatically try to recover by restarting the Splunk Enterprise pods on another machine that is able to reuse the same data volumes. This minimizes the maintenance burden on your operations team by reducing the impact of common hardware failures to the equivalent of a service restart. +The use of Persistent Volume Claims requires that your cluster is configured to support one or more Kubernetes persistent [Storage Classes](https://kubernetes.io/docs/concepts/storage/storage-classes/). See the [Setting Up a Persistent Storage for Splunk](/configuration/StorageClass) page for more +information. + +### What Storage Type To Use? + +The Kubernetes infrastructure must have access to storage that meets or exceeds the recommendations provided in the Splunk Enterprise storage type recommendations at [Reference Hardware documentation - what storage type to use for a given role?](https://docs.splunk.com/Documentation/Splunk/latest/Capacity/Referencehardware#What_storage_type_should_I_use_for_a_role.3F) In summary, Indexers with SmartStore need NVMe or SSD storage to provide the necessary IOPs for a successful Splunk Enterprise environment. + + +### Splunk SmartStore Required +For production environments, we are requiring the use of Splunk SmartStore. As a Splunk Enterprise deployment's data volume increases, demand for storage typically outpaces demand for compute resources. [Splunk's SmartStore Feature](https://docs.splunk.com/Documentation/Splunk/latest/Indexer/AboutSmartStore) allows you to manage your indexer storage and compute resources in a ___cost-effective___ manner by scaling those resources separately. SmartStore utilizes a fast storage cache on each indexer node to keep recent data locally available for search and keep other data in a remote object store. Look into the [SmartStore Resource Guide](/configuration/SmartStore) document for configuring and using SmartStore through operator. diff --git a/docs/pages/support.md b/docs/pages/support.md new file mode 100644 index 000000000..b81f20aed --- /dev/null +++ b/docs/pages/support.md @@ -0,0 +1,28 @@ +--- +title: Support +nav_order: 90 +nav_after_collections: true +permalink: /Support +--- + +## Support Resources + +SPLUNK SUPPORTED: The Splunk Operator for Kubernetes is a supported method for deploying distributed Splunk Enterprise environments using containers. The Splunk Operator is categorized as an Extension and subject to the support terms found [here](https://www.splunk.com/en_us/legal/splunk-software-support-policy.html). Splunk Enterprise deployed using the Splunk Operator is subject to the applicable support level offered [here](https://www.splunk.com/en_us/customer-success/support-programs.html). + +COMMUNITY DEVELOPED: Splunk Operator for Kubernetes is an open source product developed by Splunkers with contributions from the community of partners and customers. The primary reason why Splunk is taking this approach is to push product development closer to those that use and depend upon it. This direct connection will help us all be more successful and move at a rapid pace. + +If you're interested in contributing to the SOK open source project, review the [Contributing to the Project](/Contributing) page. + +**Community Support & Discussions on +[Slack](https://splunk-usergroups.slack.com)** channel #splunk-operator-for-kubernetes + +**File Issues or Enhancements in +[GitHub](https://github.com/splunk/splunk-operator/issues)** splunk/splunk-operator + +## Contacting Support + +If you are a Splunk Enterprise customer with a valid support entitlement contract and have a Splunk-related question, you can open a support case on the https://www.splunk.com/ support portal. + +## Known Issues for the Splunk Operator + +Review the [Change Log](/ChangeLog) page for a history of changes in each release. \ No newline at end of file diff --git a/go.mod b/go.mod index 656ba090e..1bc357ff5 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,14 @@ module github.com/splunk/splunk-operator -go 1.19 +go 1.21 require ( github.com/aws/aws-sdk-go v1.42.16 - github.com/go-logr/logr v1.2.4 - github.com/google/go-cmp v0.5.9 + github.com/go-logr/logr v1.3.0 + github.com/google/go-cmp v0.6.0 github.com/minio/minio-go/v7 v7.0.16 - github.com/onsi/ginkgo/v2 v2.12.1 - github.com/onsi/gomega v1.27.10 + github.com/onsi/ginkgo/v2 v2.14.0 + github.com/onsi/gomega v1.30.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 github.com/stretchr/testify v1.8.1 @@ -70,13 +70,13 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/crypto v0.1.0 // indirect - golang.org/x/net v0.14.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect - golang.org/x/sys v0.12.0 // indirect + golang.org/x/sys v0.15.0 // indirect golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.12.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.12.0 // indirect + golang.org/x/tools v0.16.1 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index f5ca52069..63f4f77ea 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.42.16 h1:jOUmYYpC77NZYQVHTOTFT4lwFBT1u3s8ETKciU4l6gQ= github.com/aws/aws-sdk-go v1.42.16/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= @@ -68,6 +69,7 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -94,8 +96,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -156,8 +158,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -251,12 +253,12 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= -github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= -github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= -github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs= +github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= +github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= +github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -332,6 +334,7 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= @@ -370,7 +373,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -431,10 +435,10 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -446,10 +450,10 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -500,10 +504,10 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= -golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/helm-chart/splunk-enterprise/Chart.yaml b/helm-chart/splunk-enterprise/Chart.yaml index 5ffda823f..e2247b3b8 100644 --- a/helm-chart/splunk-enterprise/Chart.yaml +++ b/helm-chart/splunk-enterprise/Chart.yaml @@ -15,22 +15,20 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 2.4.0 +version: 2.5.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "2.4.0" +appVersion: "2.5.0" maintainers: - name: Vivek Reddy email: vivekr@splunk.com - name: Arjun Kondur email: akondur@splunk.com - - name: Gaurav Gupta - email: gaurav@splunk.com dependencies: - name: splunk-operator - version: "2.3.0" + version: "2.5.0" repository: "file://splunk-operator/helm-chart/splunk-operator" condition: splunk-operator.enabled diff --git a/helm-chart/splunk-enterprise/charts/splunk-operator-2.5.0.tgz b/helm-chart/splunk-enterprise/charts/splunk-operator-2.5.0.tgz new file mode 100644 index 000000000..0e427094d Binary files /dev/null and b/helm-chart/splunk-enterprise/charts/splunk-operator-2.5.0.tgz differ diff --git a/helm-chart/splunk-enterprise/templates/enterprise_v4_indexercluster.yaml b/helm-chart/splunk-enterprise/templates/enterprise_v4_indexercluster.yaml index 112b8c7ff..09e90481e 100644 --- a/helm-chart/splunk-enterprise/templates/enterprise_v4_indexercluster.yaml +++ b/helm-chart/splunk-enterprise/templates/enterprise_v4_indexercluster.yaml @@ -143,7 +143,7 @@ items: {{- end }} {{- if $.Values.indexerCluster.topologySpreadConstraints }} {{- with $.Values.indexerCluster.topologySpreadConstraints }} - topologySpreadConstraints: + topologySpreadConstraints: {{ toYaml . | indent 6 }} {{- end }} {{- end }} diff --git a/helm-chart/splunk-enterprise/templates/enterprise_v4_licensemanager.yaml b/helm-chart/splunk-enterprise/templates/enterprise_v4_licensemanager.yaml index 74c8d7174..26625f137 100644 --- a/helm-chart/splunk-enterprise/templates/enterprise_v4_licensemanager.yaml +++ b/helm-chart/splunk-enterprise/templates/enterprise_v4_licensemanager.yaml @@ -9,12 +9,12 @@ metadata: {{ toYaml . | indent 4 }} {{- end }} {{- with .Values.licenseManager.additionalAnnotations }} - annotations: + annotations: {{ toYaml . | indent 4 }} {{- end }} spec: {{- with .Values.licenseManager.appRepo }} - appRepo: + appRepo: {{ toYaml . | indent 4 }} {{- end }} {{- if .Values.existingClusterManager }} @@ -53,7 +53,7 @@ spec: imagePullSecrets: {{ toYaml . | indent 4 }} {{- end }} -{{- with .Values.licenseManager.volumes }} +{{- with .Values.licenseManager.volumes }} volumes: {{ toYaml . | indent 4 }} {{- end }} diff --git a/helm-chart/splunk-enterprise/values.yaml b/helm-chart/splunk-enterprise/values.yaml index 45bf85e1c..027f8fb78 100644 --- a/helm-chart/splunk-enterprise/values.yaml +++ b/helm-chart/splunk-enterprise/values.yaml @@ -240,7 +240,7 @@ clusterManager: # Define affinity scheduling rules # reference: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#affinity-v1-core affinity: {} - ## Example: schedule Splunk instance pod on a node in zone-1a + ## Example: schedule Splunk instance pod on a node in zone-1a # nodeAffinity: # requiredDuringSchedulingIgnoredDuringExecution: # nodeSelectorTerms: @@ -385,9 +385,9 @@ searchHeadCluster: # endpoint: # region: # secretRef: - + volumes: [] - + licenseUrl: "" defaultsUrl: "" @@ -397,8 +397,8 @@ searchHeadCluster: defaultsUrlApps: "" extraEnv: [] - # - name: - # value: + # - name: + # value: livenessInitialDelaySeconds: 300 @@ -438,7 +438,7 @@ searchHeadCluster: # cpu: "4" # limits: # memory: "12Gi" - # cpu: "24" + # cpu: "24" serviceAccount: "" @@ -598,7 +598,7 @@ licenseManager: # endpoint: # region: # secretRef: - + volumes: [] ## Example: mounting volume containing license in Splunk instance pod container # - name: licenses diff --git a/helm-chart/splunk-operator/Chart.yaml b/helm-chart/splunk-operator/Chart.yaml index d2b8ce2de..8748cf5bb 100644 --- a/helm-chart/splunk-operator/Chart.yaml +++ b/helm-chart/splunk-operator/Chart.yaml @@ -6,8 +6,6 @@ maintainers: email: vivekr@splunk.com - name: Arjun Kondur email: akondur@splunk.com - - name: Gaurav Gupta - email: gaurav@splunk.com # A chart can be either an 'application' or a 'library' chart. # # Application charts are a collection of templates that can be packaged into versioned archives @@ -21,10 +19,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: "2.4.0" +version: "2.5.0" # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "2.4.0" \ No newline at end of file +appVersion: "2.5.0" \ No newline at end of file diff --git a/helm-chart/splunk-operator/templates/app_download.yaml b/helm-chart/splunk-operator/templates/app_download.yaml index 5d94721fe..5364d433d 100644 --- a/helm-chart/splunk-operator/templates/app_download.yaml +++ b/helm-chart/splunk-operator/templates/app_download.yaml @@ -19,8 +19,8 @@ spec: storage: 10Gi {{- end }} volumeMode: Filesystem -{{- if $volume.storageClassName }} - storageClassName: {{ $volume.storageClassName }} +{{- if $.Values.splunkOperator.persistentVolumeClaim.storageClassName }} + storageClassName: {{ $.Values.splunkOperator.persistentVolumeClaim.storageClassName }} {{- end }} --- diff --git a/helm-chart/splunk-operator/values.yaml b/helm-chart/splunk-operator/values.yaml index b41d28b67..120420278 100644 --- a/helm-chart/splunk-operator/values.yaml +++ b/helm-chart/splunk-operator/values.yaml @@ -1,6 +1,9 @@ +splunk-operator: + enabled: true + # Splunk image image: - repository: docker.io/splunk/splunk:9.1.1 + repository: docker.io/splunk/splunk:9.1.3 # The kube-rbac-proxy is a small HTTP proxy for a single upstream, that can perform RBAC # authorization against the Kubernetes API. @@ -29,7 +32,7 @@ splunkOperator: # Splunk operator image and pull policy # reference: https://github.com/splunk/splunk-operator image: - repository: docker.io/splunk/splunk-operator:2.3.0 + repository: docker.io/splunk/splunk-operator:2.5.0 pullPolicy: IfNotPresent # Set image pull secrets to pull image from a private registry @@ -58,6 +61,15 @@ splunkOperator: # reference: https://kubernetes.io/docs/concepts/security/pod-security-policy/#privilege-escalation containerSecurityContext: allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - "ALL" + add: + - "NET_BIND_SERVICE" + seccompProfile: + type: "RuntimeDefault" # Set security context for Splunk Operator pod # reference: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#podsecuritycontext-v1-core @@ -129,6 +141,10 @@ splunkOperator: # reference: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#pod-v1-core terminationGracePeriodSeconds: 10 + # Set storageClassName for the PersistentVolumeClaim + persistentVolumeClaim: + storageClassName: "default" + # Specify volumes for Splunk Operator pod, append additional volumes to list # reference: https://kubernetes.io/docs/concepts/storage/volumes/ volumes: diff --git a/kuttl/kuttl-test-helm-upgrade.yaml b/kuttl/kuttl-test-helm-upgrade.yaml new file mode 100644 index 000000000..d8ecc7336 --- /dev/null +++ b/kuttl/kuttl-test-helm-upgrade.yaml @@ -0,0 +1,10 @@ +# Entrypoint for helm automation +apiVersion: kuttl.dev/v1beta1 +kind: TestSuite +testDirs: +- ./kuttl/tests/upgrade +parallel: 3 +timeout: 5000 +startKIND: false +artifactsDir: kuttl-artifacts +kindNodeCache: false diff --git a/kuttl/tests/helm/c3-with-apps-private-link/03-install-c3.yaml b/kuttl/tests/helm/c3-with-apps-private-link/03-install-c3.yaml index d5a3330d1..428664a12 100644 --- a/kuttl/tests/helm/c3-with-apps-private-link/03-install-c3.yaml +++ b/kuttl/tests/helm/c3-with-apps-private-link/03-install-c3.yaml @@ -2,5 +2,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-c3 $HELM_REPO_PATH/splunk-enterprise -f c3_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-c3 $HELM_REPO_PATH/splunk-enterprise -f c3_config.yaml --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true \ No newline at end of file diff --git a/kuttl/tests/helm/c3-with-apps-private-link/c3_config.yaml b/kuttl/tests/helm/c3-with-apps-private-link/c3_config.yaml index 12138918f..53c3adc63 100644 --- a/kuttl/tests/helm/c3-with-apps-private-link/c3_config.yaml +++ b/kuttl/tests/helm/c3-with-apps-private-link/c3_config.yaml @@ -4,6 +4,8 @@ splunk-operator: serviceAccountName: "splunk-enterprise-serviceaccount-staging" splunkOperator: clusterWideAccess: false + persistentVolumeClaim: + storageClassName: gp2 sva: c3: enabled: true diff --git a/kuttl/tests/helm/c3-with-apps/03-install-c3.yaml b/kuttl/tests/helm/c3-with-apps/03-install-c3.yaml index d5a3330d1..428664a12 100644 --- a/kuttl/tests/helm/c3-with-apps/03-install-c3.yaml +++ b/kuttl/tests/helm/c3-with-apps/03-install-c3.yaml @@ -2,5 +2,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-c3 $HELM_REPO_PATH/splunk-enterprise -f c3_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-c3 $HELM_REPO_PATH/splunk-enterprise -f c3_config.yaml --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true \ No newline at end of file diff --git a/kuttl/tests/helm/c3-with-apps/c3_config.yaml b/kuttl/tests/helm/c3-with-apps/c3_config.yaml index 07c03d950..622f61ea3 100644 --- a/kuttl/tests/helm/c3-with-apps/c3_config.yaml +++ b/kuttl/tests/helm/c3-with-apps/c3_config.yaml @@ -2,7 +2,8 @@ splunk-operator: enabled: true splunkOperator: clusterWideAccess: false - + persistentVolumeClaim: + storageClassName: gp2 sva: c3: diff --git a/kuttl/tests/helm/c3-with-operator/00-install-c3.yaml b/kuttl/tests/helm/c3-with-operator/00-install-c3.yaml index d5a3330d1..428664a12 100644 --- a/kuttl/tests/helm/c3-with-operator/00-install-c3.yaml +++ b/kuttl/tests/helm/c3-with-operator/00-install-c3.yaml @@ -2,5 +2,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-c3 $HELM_REPO_PATH/splunk-enterprise -f c3_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-c3 $HELM_REPO_PATH/splunk-enterprise -f c3_config.yaml --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true \ No newline at end of file diff --git a/kuttl/tests/helm/c3/c3_config.yaml b/kuttl/tests/helm/c3/c3_config.yaml index d4d43592c..e41af84a0 100644 --- a/kuttl/tests/helm/c3/c3_config.yaml +++ b/kuttl/tests/helm/c3/c3_config.yaml @@ -1,5 +1,9 @@ splunk-operator: enabled: false + splunkOperator: + clusterWideAccess: false + persistentVolumeClaim: + storageClassName: gp2 sva: c3: diff --git a/kuttl/tests/helm/m4-with-operator/00-install-m4.yaml b/kuttl/tests/helm/m4-with-operator/00-install-m4.yaml index ecbb45a2b..9503d8593 100644 --- a/kuttl/tests/helm/m4-with-operator/00-install-m4.yaml +++ b/kuttl/tests/helm/m4-with-operator/00-install-m4.yaml @@ -2,5 +2,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-m4 $HELM_REPO_PATH/splunk-enterprise -f m4_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-m4 $HELM_REPO_PATH/splunk-enterprise -f m4_config.yaml --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true diff --git a/kuttl/tests/helm/m4-with-operator/m4_config.yaml b/kuttl/tests/helm/m4-with-operator/m4_config.yaml index 22a097ce1..b6c5b1b1c 100644 --- a/kuttl/tests/helm/m4-with-operator/m4_config.yaml +++ b/kuttl/tests/helm/m4-with-operator/m4_config.yaml @@ -2,6 +2,8 @@ splunk-operator: enabled: true splunkOperator: clusterWideAccess: false + persistentVolumeClaim: + storageClassName: gp2 sva: m4: diff --git a/kuttl/tests/helm/m4/m4_config.yaml b/kuttl/tests/helm/m4/m4_config.yaml index ed6acd85b..a14e05bd8 100644 --- a/kuttl/tests/helm/m4/m4_config.yaml +++ b/kuttl/tests/helm/m4/m4_config.yaml @@ -1,6 +1,9 @@ splunk-operator: enabled: false - + splunkOperator: + clusterWideAccess: false + persistentVolumeClaim: + storageClassName: gp2 sva: m4: enabled: true diff --git a/kuttl/tests/helm/operator-with-ephemeral-volume/01-install-standalone.yaml b/kuttl/tests/helm/operator-with-ephemeral-volume/01-install-standalone.yaml index 48500e4b5..ba3f06ec6 100644 --- a/kuttl/tests/helm/operator-with-ephemeral-volume/01-install-standalone.yaml +++ b/kuttl/tests/helm/operator-with-ephemeral-volume/01-install-standalone.yaml @@ -1,5 +1,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true diff --git a/kuttl/tests/helm/operator-with-ephemeral-volume/s1_config.yaml b/kuttl/tests/helm/operator-with-ephemeral-volume/s1_config.yaml index e1a78bdee..4892a4456 100644 --- a/kuttl/tests/helm/operator-with-ephemeral-volume/s1_config.yaml +++ b/kuttl/tests/helm/operator-with-ephemeral-volume/s1_config.yaml @@ -5,6 +5,8 @@ splunk-operator: splunkOperator: clusterWideAccess: false + persistentVolumeClaim: + storageClassName: gp2 volumes: - name: app-staging diff --git a/kuttl/tests/helm/s1-with-extra-manifests/01-install-standalone.yaml b/kuttl/tests/helm/s1-with-extra-manifests/01-install-standalone.yaml index 48500e4b5..ba3f06ec6 100644 --- a/kuttl/tests/helm/s1-with-extra-manifests/01-install-standalone.yaml +++ b/kuttl/tests/helm/s1-with-extra-manifests/01-install-standalone.yaml @@ -1,5 +1,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true diff --git a/kuttl/tests/helm/s1-with-extra-manifests/s1_config.yaml b/kuttl/tests/helm/s1-with-extra-manifests/s1_config.yaml index 2b42e840a..a1cf31893 100644 --- a/kuttl/tests/helm/s1-with-extra-manifests/s1_config.yaml +++ b/kuttl/tests/helm/s1-with-extra-manifests/s1_config.yaml @@ -4,6 +4,8 @@ splunk-operator: serviceAccountName: helm-service-account splunkOperator: clusterWideAccess: false + persistentVolumeClaim: + storageClassName: gp2 standalone: enabled: true diff --git a/kuttl/tests/helm/s1-with-operator/01-install-standalone.yaml b/kuttl/tests/helm/s1-with-operator/01-install-standalone.yaml index 48500e4b5..ba3f06ec6 100644 --- a/kuttl/tests/helm/s1-with-operator/01-install-standalone.yaml +++ b/kuttl/tests/helm/s1-with-operator/01-install-standalone.yaml @@ -1,5 +1,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true diff --git a/kuttl/tests/helm/s1-with-operator/s1_config.yaml b/kuttl/tests/helm/s1-with-operator/s1_config.yaml index 96141461e..e2a5395f7 100644 --- a/kuttl/tests/helm/s1-with-operator/s1_config.yaml +++ b/kuttl/tests/helm/s1-with-operator/s1_config.yaml @@ -4,6 +4,8 @@ splunk-operator: serviceAccountName: helm-service-account splunkOperator: clusterWideAccess: false + persistentVolumeClaim: + storageClassName: gp2 standalone: enabled: true \ No newline at end of file diff --git a/kuttl/tests/helm/s1-with-smartstore/03-install-s1.yaml b/kuttl/tests/helm/s1-with-smartstore/03-install-s1.yaml index 566b0c6cf..27d8e5bde 100644 --- a/kuttl/tests/helm/s1-with-smartstore/03-install-s1.yaml +++ b/kuttl/tests/helm/s1-with-smartstore/03-install-s1.yaml @@ -2,5 +2,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-s1 $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-s1 $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true \ No newline at end of file diff --git a/kuttl/tests/helm/s1-with-smartstore/s1_config.yaml b/kuttl/tests/helm/s1-with-smartstore/s1_config.yaml index 5ef7629c5..9045f896b 100644 --- a/kuttl/tests/helm/s1-with-smartstore/s1_config.yaml +++ b/kuttl/tests/helm/s1-with-smartstore/s1_config.yaml @@ -2,6 +2,8 @@ splunk-operator: enabled: true splunkOperator: clusterWideAccess: false + persistentVolumeClaim: + storageClassName: gp2 sva: s1: enabled: true diff --git a/kuttl/tests/helm/s1-with-topology-spread-constraints/01-install-standalone.yaml b/kuttl/tests/helm/s1-with-topology-spread-constraints/01-install-standalone.yaml index 48500e4b5..635fba212 100644 --- a/kuttl/tests/helm/s1-with-topology-spread-constraints/01-install-standalone.yaml +++ b/kuttl/tests/helm/s1-with-topology-spread-constraints/01-install-standalone.yaml @@ -1,5 +1,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true diff --git a/kuttl/tests/helm/s1-with-topology-spread-constraints/03-install-standalone.yaml b/kuttl/tests/helm/s1-with-topology-spread-constraints/03-install-standalone.yaml index 6a7faae02..698fecaaa 100644 --- a/kuttl/tests/helm/s1-with-topology-spread-constraints/03-install-standalone.yaml +++ b/kuttl/tests/helm/s1-with-topology-spread-constraints/03-install-standalone.yaml @@ -1,5 +1,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: - - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config-vanilla.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + - command: helm install splunk-stdl $HELM_REPO_PATH/splunk-enterprise -f s1_config-vanilla.yaml --set splunk-operator.splunkOperator.clusterWideAccess=false --set splunk-operator.splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} namespaced: true diff --git a/kuttl/tests/helm/s1-with-topology-spread-constraints/s1_config.yaml b/kuttl/tests/helm/s1-with-topology-spread-constraints/s1_config.yaml index 47eaa85b6..6179eb865 100644 --- a/kuttl/tests/helm/s1-with-topology-spread-constraints/s1_config.yaml +++ b/kuttl/tests/helm/s1-with-topology-spread-constraints/s1_config.yaml @@ -4,6 +4,8 @@ splunk-operator: serviceAccountName: helm-service-account splunkOperator: clusterWideAccess: false + persistentVolumeClaim: + storageClassName: gp2 standalone: enabled: true diff --git a/kuttl/tests/helm/script/installoperator.sh b/kuttl/tests/helm/script/installoperator.sh index be89ed407..9edd00e4f 100755 --- a/kuttl/tests/helm/script/installoperator.sh +++ b/kuttl/tests/helm/script/installoperator.sh @@ -2,7 +2,7 @@ if [ "${INSTALL_OPERATOR}" = true ]; then echo "installing operator" - helm install splunk-operator $HELM_REPO_PATH/splunk-operator --namespace $NAMESPACE --set splunkOperator.clusterWideAccess=false --set splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} + helm install splunk-operator $HELM_REPO_PATH/splunk-operator --namespace $NAMESPACE --set splunkOperator.persistentVolumeClaim.storageClassName=gp2 --set splunkOperator.clusterWideAccess=false --set splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} retVal=$? if [ $retVal -ne 0 ]; then echo "operator installation failed" diff --git a/kuttl/tests/upgrade/c3-with-operator/00-assert.yaml b/kuttl/tests/upgrade/c3-with-operator/00-assert.yaml new file mode 100644 index 000000000..142b71272 --- /dev/null +++ b/kuttl/tests/upgrade/c3-with-operator/00-assert.yaml @@ -0,0 +1,9 @@ +--- +# assert for splunk operator deployment to be ready +apiVersion: apps/v1 +kind: Deployment +metadata: + name: splunk-operator-controller-manager +status: + readyReplicas: 1 + availableReplicas: 1 diff --git a/kuttl/tests/upgrade/c3-with-operator/00-install-c3.yaml b/kuttl/tests/upgrade/c3-with-operator/00-install-c3.yaml new file mode 100644 index 000000000..a10c31557 --- /dev/null +++ b/kuttl/tests/upgrade/c3-with-operator/00-install-c3.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: helm install splunk-c3 $HELM_REPO_PATH/splunk-enterprise -f c3_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_IMAGE} --namespace ${NAMESPACE} + namespaced: true \ No newline at end of file diff --git a/kuttl/tests/upgrade/c3-with-operator/01-assert.yaml b/kuttl/tests/upgrade/c3-with-operator/01-assert.yaml new file mode 100644 index 000000000..4b09ebf54 --- /dev/null +++ b/kuttl/tests/upgrade/c3-with-operator/01-assert.yaml @@ -0,0 +1,9 @@ +--- +# assert for splunk operator pod to be ready +apiVersion: apps/v1 +kind: Deployment +metadata: + name: splunk-operator-controller-manager +status: + readyReplicas: 1 + availableReplicas: 1 \ No newline at end of file diff --git a/kuttl/tests/upgrade/c3-with-operator/01-upgrade-splunk-image.yaml b/kuttl/tests/upgrade/c3-with-operator/01-upgrade-splunk-image.yaml new file mode 100644 index 000000000..f5689caa5 --- /dev/null +++ b/kuttl/tests/upgrade/c3-with-operator/01-upgrade-splunk-image.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: helm upgrade splunk-c3 $HELM_REPO_PATH/splunk-enterprise --reuse-values -f c3_config.yaml --set splunk-operator.splunkOperator.image.repository=${KUTTL_SPLUNK_OPERATOR_IMAGE} --set splunk-operator.image.repository=${KUTTL_SPLUNK_ENTERPRISE_NEW_IMAGE} --namespace ${NAMESPACE} + namespaced: true \ No newline at end of file diff --git a/kuttl/tests/upgrade/c3-with-operator/02-assert.yaml b/kuttl/tests/upgrade/c3-with-operator/02-assert.yaml new file mode 100644 index 000000000..59008dd62 --- /dev/null +++ b/kuttl/tests/upgrade/c3-with-operator/02-assert.yaml @@ -0,0 +1,24 @@ +--- +# assert for cluster manager custom resource to be ready +apiVersion: enterprise.splunk.com/v4 +kind: ClusterManager +metadata: + name: cm +status: + phase: Ready + +--- +# check if stateful sets are created +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: splunk-cm-cluster-manager +status: + replicas: 1 + +--- +# check if secret object are created +apiVersion: v1 +kind: Secret +metadata: + name: splunk-cm-cluster-manager-secret-v1 diff --git a/kuttl/tests/upgrade/c3-with-operator/03-assert.yaml b/kuttl/tests/upgrade/c3-with-operator/03-assert.yaml new file mode 100644 index 000000000..c3c560798 --- /dev/null +++ b/kuttl/tests/upgrade/c3-with-operator/03-assert.yaml @@ -0,0 +1,40 @@ +--- +# assert for SearchHeadCluster custom resource to be ready +apiVersion: enterprise.splunk.com/v4 +kind: SearchHeadCluster +metadata: + name: shc +status: + phase: Ready + +--- +# check if secret object are created +apiVersion: v1 +kind: Secret +metadata: + name: splunk-shc-deployer-secret-v1 + +--- +# check if secret object are created +apiVersion: v1 +kind: Secret +metadata: + name: splunk-shc-search-head-secret-v1 + +--- +# check for stateful set and replicas as configured +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: splunk-shc-search-head +status: + replicas: 3 + +--- +# check for statefull set +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: splunk-shc-deployer +status: + replicas: 1 \ No newline at end of file diff --git a/kuttl/tests/upgrade/c3-with-operator/04-assert.yaml b/kuttl/tests/upgrade/c3-with-operator/04-assert.yaml new file mode 100644 index 000000000..368902426 --- /dev/null +++ b/kuttl/tests/upgrade/c3-with-operator/04-assert.yaml @@ -0,0 +1,24 @@ +--- +# assert for indexer cluster custom resource to be ready +apiVersion: enterprise.splunk.com/v4 +kind: IndexerCluster +metadata: + name: idxc +status: + phase: Ready + +--- +# check for stateful set and replicas as configured +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: splunk-idxc-indexer +status: + replicas: 3 + +--- +# check if secret object are created +apiVersion: v1 +kind: Secret +metadata: + name: splunk-idxc-indexer-secret-v1 diff --git a/kuttl/tests/upgrade/c3-with-operator/05-uninstall-c3.yaml b/kuttl/tests/upgrade/c3-with-operator/05-uninstall-c3.yaml new file mode 100644 index 000000000..cf9d19cf8 --- /dev/null +++ b/kuttl/tests/upgrade/c3-with-operator/05-uninstall-c3.yaml @@ -0,0 +1,5 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: helm uninstall splunk-c3 --namespace ${NAMESPACE} + namespaced: true diff --git a/kuttl/tests/upgrade/c3-with-operator/c3_config.yaml b/kuttl/tests/upgrade/c3-with-operator/c3_config.yaml new file mode 100644 index 000000000..fd00ad06d --- /dev/null +++ b/kuttl/tests/upgrade/c3-with-operator/c3_config.yaml @@ -0,0 +1,50 @@ +splunk-operator: + enabled: true + splunkOperator: + clusterWideAccess: false + +sva: + c3: + enabled: true + + clusterManager: + name: cm + + indexerClusters: + - name: idxc + + searchHeadClusters: + - name: shc + + +indexerCluster: + enabled: true + + additionalLabels: + label: "true" + + additionalAnnotations: + annotation: "true" + service.beta.kubernetes.io/azure-load-balancer-internal: "true" + + serviceTemplate: + spec: + type: LoadBalancer + +clusterManager: + enabled: true + + additionalLabels: + label: "true" + + additionalAnnotations: + annotation: "true" + +searchHeadCluster: + enabled: true + + additionalLabels: + label: "true" + + additionalAnnotations: + annotation: "true" diff --git a/pkg/splunk/controller/statefulset.go b/pkg/splunk/controller/statefulset.go index 15b31361b..c43938e17 100644 --- a/pkg/splunk/controller/statefulset.go +++ b/pkg/splunk/controller/statefulset.go @@ -351,7 +351,10 @@ func DeleteReferencesToAutomatedMCIfExists(ctx context.Context, client splcommon // isCurrentCROwner returns true if current CR is the ONLY owner of the automated MC func isCurrentCROwner(cr splcommon.MetaObject, currentOwners []metav1.OwnerReference) bool { - return reflect.DeepEqual(currentOwners[0].UID, cr.GetUID()) + // adding extra verification as unit test cases fails since fakeclient do not set UID + return reflect.DeepEqual(currentOwners[0].UID, cr.GetUID()) && + (currentOwners[0].Kind == cr.GetObjectKind().GroupVersionKind().Kind) && + (currentOwners[0].Name == cr.GetName()) } // IsStatefulSetScalingUpOrDown checks if we are currently scaling up or down diff --git a/pkg/splunk/enterprise/clustermanager.go b/pkg/splunk/enterprise/clustermanager.go index d45206475..c5d5eea0d 100644 --- a/pkg/splunk/enterprise/clustermanager.go +++ b/pkg/splunk/enterprise/clustermanager.go @@ -23,6 +23,7 @@ import ( enterpriseApi "github.com/splunk/splunk-operator/api/v4" "sigs.k8s.io/controller-runtime/pkg/client" + rclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/go-logr/logr" splclient "github.com/splunk/splunk-operator/pkg/splunk/client" @@ -31,6 +32,8 @@ import ( splutil "github.com/splunk/splunk-operator/pkg/splunk/util" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -47,7 +50,7 @@ func ApplyClusterManager(ctx context.Context, client splcommon.ControllerClient, reqLogger := log.FromContext(ctx) scopedLog := reqLogger.WithName("ApplyClusterManager") eventPublisher, _ := newK8EventPublisher(client, cr) - + cr.Kind = "ClusterManager" if cr.Status.ResourceRevMap == nil { cr.Status.ResourceRevMap = make(map[string]string) } @@ -121,7 +124,7 @@ func ApplyClusterManager(ctx context.Context, client splcommon.ControllerClient, // check if deletion has been requested if cr.ObjectMeta.DeletionTimestamp != nil { if cr.Spec.MonitoringConsoleRef.Name != "" { - extraEnv, _ := VerifyCMisMultisite(ctx, cr, namespaceScopedSecret) + extraEnv, _ := VerifyCMisMultisiteCall(ctx, cr, namespaceScopedSecret) _, err = ApplyMonitoringConsoleEnvConfigMap(ctx, client, cr.GetNamespace(), cr.GetName(), cr.Spec.MonitoringConsoleRef.Name, extraEnv, false) if err != nil { return result, err @@ -171,12 +174,18 @@ func ApplyClusterManager(ctx context.Context, client splcommon.ControllerClient, } //make changes to respective mc configmap when changing/removing mcRef from spec - extraEnv, err := VerifyCMisMultisite(ctx, cr, namespaceScopedSecret) + extraEnv, err := VerifyCMisMultisiteCall(ctx, cr, namespaceScopedSecret) err = validateMonitoringConsoleRef(ctx, client, statefulSet, extraEnv) if err != nil { return result, err } + // check if the ClusterManager is ready for version upgrade, if required + continueReconcile, err := UpgradePathValidation(ctx, client, cr, cr.Spec.CommonSplunkSpec, nil) + if err != nil || !continueReconcile { + return result, err + } + clusterManagerManager := splctrl.DefaultStatefulSetPodManager{} phase, err := clusterManagerManager.Update(ctx, client, statefulSet, 1) if err != nil { @@ -223,6 +232,12 @@ func ApplyClusterManager(ctx context.Context, client splcommon.ControllerClient, finalResult := handleAppFrameworkActivity(ctx, client, cr, &cr.Status.AppContext, &cr.Spec.AppFrameworkConfig) result = *finalResult + + // trigger MonitoringConsole reconcile by changing the splunk/image-tag annotation + err = changeMonitoringConsoleAnnotations(ctx, client, cr) + if err != nil { + return result, err + } } // RequeueAfter if greater than 0, tells the Controller to requeue the reconcile key after the Duration. // Implies that Requeue is true, there is no need to set Requeue to true at the same time as RequeueAfter. @@ -416,8 +431,8 @@ func getClusterManagerList(ctx context.Context, c splcommon.ControllerClient, cr return numOfObjects, nil } -// VerifyCMisMultisite checks if its a multisite -func VerifyCMisMultisite(ctx context.Context, cr *enterpriseApi.ClusterManager, namespaceScopedSecret *corev1.Secret) ([]corev1.EnvVar, error) { +// VerifyCMisMultisite checks if its a multisite used also in mock +var VerifyCMisMultisiteCall = func(ctx context.Context, cr *enterpriseApi.ClusterManager, namespaceScopedSecret *corev1.Secret) ([]corev1.EnvVar, error) { var err error reqLogger := log.FromContext(ctx) scopedLog := reqLogger.WithName("Verify if Multisite Indexer Cluster").WithValues("name", cr.GetName(), "namespace", cr.GetNamespace()) @@ -434,3 +449,70 @@ func VerifyCMisMultisite(ctx context.Context, cr *enterpriseApi.ClusterManager, } return extraEnv, err } + +// changeClusterManagerAnnotations updates the splunk/image-tag field of the ClusterManager annotations to trigger the reconcile loop +// on update, and returns error if something is wrong +func changeClusterManagerAnnotations(ctx context.Context, c splcommon.ControllerClient, cr *enterpriseApi.LicenseManager) error { + reqLogger := log.FromContext(ctx) + scopedLog := reqLogger.WithName("changeClusterManagerAnnotations").WithValues("name", cr.GetName(), "namespace", cr.GetNamespace()) + eventPublisher, _ := newK8EventPublisher(c, cr) + + clusterManagerInstance := &enterpriseApi.ClusterManager{} + if len(cr.Spec.ClusterManagerRef.Name) > 0 { + // if the LicenseManager holds the ClusterManagerRef + namespacedName := types.NamespacedName{ + Namespace: cr.GetNamespace(), + Name: cr.Spec.ClusterManagerRef.Name, + } + err := c.Get(ctx, namespacedName, clusterManagerInstance) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil + } + return err + } + } else { + // List out all the ClusterManager instances in the namespace + opts := []rclient.ListOption{ + rclient.InNamespace(cr.GetNamespace()), + } + objectList := enterpriseApi.ClusterManagerList{} + err := c.List(ctx, &objectList, opts...) + if err != nil { + if err.Error() == "NotFound" { + return nil + } + return err + } + if len(objectList.Items) == 0 { + return nil + } + + // check if instance has the required LicenseManagerRef + for _, cm := range objectList.Items { + if cm.Spec.LicenseManagerRef.Name == cr.GetName() { + clusterManagerInstance = &cm + break + } + } + + if len(clusterManagerInstance.GetName()) == 0 { + return nil + } + } + + image, err := getCurrentImage(ctx, c, cr, SplunkLicenseManager) + if err != nil { + eventPublisher.Warning(ctx, "changeClusterManagerAnnotations", fmt.Sprintf("Could not get the LicenseManager Image. Reason %v", err)) + scopedLog.Error(err, "Get LicenseManager Image failed with", "error", err) + return err + } + err = changeAnnotations(ctx, c, image, clusterManagerInstance) + if err != nil { + eventPublisher.Warning(ctx, "changeClusterManagerAnnotations", fmt.Sprintf("Could not update annotations. Reason %v", err)) + scopedLog.Error(err, "ClusterManager types update after changing annotations failed with", "error", err) + return err + } + + return nil +} diff --git a/pkg/splunk/enterprise/clustermanager_test.go b/pkg/splunk/enterprise/clustermanager_test.go index a75326a1e..4c1a16d38 100644 --- a/pkg/splunk/enterprise/clustermanager_test.go +++ b/pkg/splunk/enterprise/clustermanager_test.go @@ -138,6 +138,7 @@ func TestApplyClusterManager(t *testing.T) { } c := spltest.NewMockClient() _ = errors.New(splcommon.Rerr) + current.Kind = "ClusterManager" _, err := ApplyClusterManager(ctx, c, ¤t) if err == nil { t.Errorf("Expected error") @@ -204,6 +205,7 @@ func TestApplyClusterManager(t *testing.T) { }, } + current.Kind = "ClusterManager" _, err = ApplyClusterManager(ctx, c, ¤t) if err == nil { t.Errorf("Expected error") @@ -220,6 +222,7 @@ func TestApplyClusterManager(t *testing.T) { current.Spec.SmartStore.VolList[0].SecretRef = "s3-secret" current.Status.SmartStore.VolList[0].SecretRef = "s3-secret" current.Status.ResourceRevMap["s3-secret"] = "v2" + current.Kind = "ClusterManager" _, err = ApplyClusterManager(ctx, c, ¤t) if err == nil { t.Errorf("Expected error") @@ -234,6 +237,7 @@ func TestApplyClusterManager(t *testing.T) { c.Create(ctx, &cmap) current.Spec.SmartStore.VolList[0].SecretRef = "" current.Spec.SmartStore.Defaults.IndexAndGlobalCommonSpec.VolName = "msos_s2s3_vol" + current.Kind = "ClusterManager" _, err = ApplyClusterManager(ctx, c, ¤t) if err != nil { t.Errorf("Don't expected error here") @@ -290,6 +294,7 @@ func TestApplyClusterManager(t *testing.T) { }, }, } + current.Kind = "ClusterManager" _, err = ApplyClusterManager(ctx, c, ¤t) if err == nil { t.Errorf("Expected error") @@ -307,6 +312,7 @@ func TestApplyClusterManager(t *testing.T) { } rerr := errors.New(splcommon.Rerr) c.InduceErrorKind[splcommon.MockClientInduceErrorGet] = rerr + current.Kind = "ClusterManager" _, err = ApplyClusterManager(ctx, c, ¤t) if err == nil { t.Errorf("Expected error") @@ -442,18 +448,18 @@ func TestGetClusterManagerStatefulSet(t *testing.T) { } configTester(t, "getClusterManagerStatefulSet", f, want) } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.LicenseManagerRef.Name = "stack1" cr.Spec.LicenseManagerRef.Namespace = "test" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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_LICENSE_MASTER_URL","value":"splunk-stack1-license-manager-service.test.svc.cluster.local"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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_LICENSE_MASTER_URL","value":"splunk-stack1-license-manager-service.test.svc.cluster.local"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.LicenseManagerRef.Name = "" cr.Spec.LicenseURL = "/mnt/splunk.lic" - test(` {"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.DefaultsURLApps = "/mnt/apps/apps.yml" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Create a serviceaccount current := corev1.ServiceAccount{ @@ -464,7 +470,7 @@ func TestGetClusterManagerStatefulSet(t *testing.T) { } _ = splutil.CreateResource(ctx, c, ¤t) cr.Spec.ServiceAccount = "defaults" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Add extraEnv cr.Spec.CommonSplunkSpec.ExtraEnv = []corev1.EnvVar{ @@ -473,7 +479,7 @@ func TestGetClusterManagerStatefulSet(t *testing.T) { Value: "test_value", }, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-manager","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) } @@ -531,9 +537,14 @@ func TestApplyClusterManagerWithSmartstore(t *testing.T) { runtime.InNamespace("test"), runtime.MatchingLabels(labels), } + listOpts1 := []runtime.ListOption{ + runtime.InNamespace("test"), + } listmockCall := []spltest.MockFuncCall{ - {ListOpts: listOpts}} - createCalls := map[string][]spltest.MockFuncCall{"Get": funcCalls, "Create": {funcCalls[7], funcCalls[10], funcCalls[12]}, "List": {listmockCall[0], listmockCall[0]}, "Update": {funcCalls[0], funcCalls[3], funcCalls[13]}} + {ListOpts: listOpts}, + {ListOpts: listOpts1}, + } + createCalls := map[string][]spltest.MockFuncCall{"Get": funcCalls, "Create": {funcCalls[7], funcCalls[10], funcCalls[12]}, "List": {listmockCall[0], listmockCall[0], listmockCall[1]}, "Update": {funcCalls[0], funcCalls[3], funcCalls[13]}} updateCalls := map[string][]spltest.MockFuncCall{"Get": updateFuncCalls, "Update": {funcCalls[8]}, "List": {listmockCall[0]}} current := enterpriseApi.ClusterManager{ @@ -578,6 +589,7 @@ func TestApplyClusterManagerWithSmartstore(t *testing.T) { } // Without S3 keys, ApplyClusterManager should fail + current.Kind = "ClusterManager" _, err := ApplyClusterManager(ctx, client, ¤t) if err == nil { t.Errorf("ApplyClusterManager should fail without S3 secrets configured") @@ -607,6 +619,7 @@ func TestApplyClusterManagerWithSmartstore(t *testing.T) { revised := current.DeepCopy() revised.Spec.Image = "splunk/test" reconcile := func(c *spltest.MockClient, cr interface{}) error { + current.Kind = "ClusterManager" _, err := ApplyClusterManager(context.Background(), c, cr.(*enterpriseApi.ClusterManager)) return err } @@ -634,6 +647,7 @@ func TestApplyClusterManagerWithSmartstore(t *testing.T) { spltest.ReconcileTesterWithoutRedundantCheck(t, "TestApplyClusterManagerWithSmartstore-0", ¤t, revised, createCalls, updateCalls, reconcile, true, secret, &smartstoreConfigMap, ss, pod) current.Status.BundlePushTracker.NeedToPushManagerApps = true + current.Kind = "ClusterManager" if _, err = ApplyClusterManager(context.Background(), client, ¤t); err != nil { t.Errorf("ApplyClusterManager() should not have returned error") } @@ -861,13 +875,14 @@ func TestAppFrameworkApplyClusterManagerShouldNotFail(t *testing.T) { t.Errorf(err.Error()) } + cm.Kind = "ClusterManager" _, err = ApplyClusterManager(context.Background(), client, &cm) if err != nil { t.Errorf("ApplyClusterManager should not have returned error here.") } } -func TestApplyCLusterManagerDeletion(t *testing.T) { +func TestApplyClusterManagerDeletion(t *testing.T) { ctx := context.TODO() cm := enterpriseApi.ClusterManager{ ObjectMeta: metav1.ObjectMeta{ @@ -955,7 +970,7 @@ func TestApplyCLusterManagerDeletion(t *testing.T) { if err != nil { t.Errorf("Unable to create download directory for apps :%s", splcommon.AppDownloadVolume) } - + cm.Kind = "ClusterManager" _, err = ApplyClusterManager(ctx, c, &cm) if err != nil { t.Errorf("ApplyClusterManager should not have returned error here.") @@ -1384,6 +1399,231 @@ func TestCheckIfsmartstoreConfigMapUpdatedToPod(t *testing.T) { mockPodExecClient.CheckPodExecCommands(t, "CheckIfsmartstoreConfigMapUpdatedToPod") } +func TestIsClusterManagerReadyForUpgrade(t *testing.T) { + ctx := context.TODO() + + builder := fake.NewClientBuilder() + client := builder.Build() + utilruntime.Must(enterpriseApi.AddToScheme(clientgoscheme.Scheme)) + + // Create License Manager + lm := enterpriseApi.LicenseManager{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.LicenseManagerSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + Image: "splunk/splunk:latest", + }, + Volumes: []corev1.Volume{}, + ClusterManagerRef: corev1.ObjectReference{ + Name: "test", + }, + }, + }, + } + + err := client.Create(ctx, &lm) + _, err = ApplyLicenseManager(ctx, client, &lm) + if err != nil { + t.Errorf("applyLicenseManager should not have returned error; err=%v", err) + } + namespacedName := types.NamespacedName{ + Name: "test", + Namespace: "test", + } + err = client.Get(ctx, namespacedName, &lm) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + lm.Status.Phase = enterpriseApi.PhaseReady + err = client.Status().Update(ctx, &lm) + if err != nil { + t.Errorf("Unexpected status update %v", err) + debug.PrintStack() + } + + // Create Cluster Manager + cm := enterpriseApi.ClusterManager{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.ClusterManagerSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + Image: "splunk/splunk:latest", + }, + Volumes: []corev1.Volume{}, + LicenseManagerRef: corev1.ObjectReference{ + Name: "test", + }, + }, + }, + } + + cm.Kind = "ClusterManager" + err = client.Create(ctx, &cm) + _, err = ApplyClusterManager(ctx, client, &cm) + if err != nil { + t.Errorf("applyClusterManager should not have returned error; err=%v", err) + } + + // create pods for license manager + lm.Status.TelAppInstalled = true + lm.Spec.Image = "splunk2" + createPods(t, ctx, client, "license-manager", fmt.Sprintf("splunk-%s-license-manager-0", lm.Name), lm.Namespace, lm.Spec.Image) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-license-manager", lm.Name), lm.Namespace) + // now the statefulset image in spec is updated to splunk2 + _, err = ApplyLicenseManager(ctx, client, &lm) + + // now the statefulset and license manager both should be in ready state + _, err = ApplyLicenseManager(ctx, client, &lm) + + clusterManager := &enterpriseApi.ClusterManager{} + namespacedName = types.NamespacedName{ + Name: cm.Name, + Namespace: cm.Namespace, + } + err = client.Get(ctx, namespacedName, clusterManager) + if err != nil { + t.Errorf("changeClusterManagerAnnotations should not have returned error=%v", err) + } + clusterManager.Spec.Image = "splunk2" + err = client.Update(ctx, clusterManager) + if err != nil { + t.Errorf("update should not have returned error; err=%v", err) + } + + check, err := UpgradePathValidation(ctx, client, clusterManager, clusterManager.Spec.CommonSplunkSpec, nil) + + if err != nil { + t.Errorf("Unexpected upgradeScenario error %v", err) + } + + if !check { + t.Errorf("isClusterManagerReadyForUpgrade: CM should be ready for upgrade") + } +} + +func TestChangeClusterManagerAnnotations(t *testing.T) { + ctx := context.TODO() + + // define LM and CM + lm := &enterpriseApi.LicenseManager{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-lm", + Namespace: "test", + }, + Spec: enterpriseApi.LicenseManagerSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + Image: "splunk/splunk:latest", + ImagePullPolicy: "Always", + }, + Volumes: []corev1.Volume{}, + }, + }, + } + + cm := &enterpriseApi.ClusterManager{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cm", + Namespace: "test", + }, + Spec: enterpriseApi.ClusterManagerSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + Image: "splunk/splunk:latest", + ImagePullPolicy: "Always", + }, + Volumes: []corev1.Volume{}, + LicenseManagerRef: corev1.ObjectReference{ + Name: "test-lm", + }, + }, + }, + } + lm.Spec.Image = "splunk/splunk:latest" + + builder := fake.NewClientBuilder() + client := builder.Build() + utilruntime.Must(enterpriseApi.AddToScheme(clientgoscheme.Scheme)) + + // Create the instances + client.Create(ctx, lm) + _, err := ApplyLicenseManager(ctx, client, lm) + if err != nil { + t.Errorf("applyLicenseManager should not have returned error; err=%v", err) + } + + namespacedName := types.NamespacedName{ + Name: lm.Name, + Namespace: lm.Namespace, + } + err = client.Get(ctx, namespacedName, lm) + if err != nil { + t.Errorf("changeLicenseManagerAnnotations should not have returned error=%v", err) + } + + // create pods for license manager + createPods(t, ctx, client, "license-manager", fmt.Sprintf("splunk-%s-license-manager-0", lm.Name), lm.Namespace, lm.Spec.Image) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-license-manager", lm.Name), lm.Namespace) + lm.Status.TelAppInstalled = true + // create license manager statefulset + _, err = ApplyLicenseManager(ctx, client, lm) + if err != nil { + t.Errorf("ApplyLicenseManager should not have returned error; err=%v", err) + } + + err = client.Get(ctx, namespacedName, lm) + if err != nil { + t.Errorf("changeLicenseManagerAnnotations should not have returned error=%v", err) + } + + lm.Status.Phase = enterpriseApi.PhaseReady + err = client.Status().Update(ctx, lm) + if err != nil { + t.Errorf("Unexpected update pod %v", err) + debug.PrintStack() + } + + VerifyCMisMultisiteCall = func(ctx context.Context, cr *enterpriseApi.ClusterManager, namespaceScopedSecret *corev1.Secret) ([]corev1.EnvVar, error) { + extraEnv := getClusterManagerExtraEnv(cr, &cr.Spec.CommonSplunkSpec) + return extraEnv, err + } + + cm.Kind = "ClusterManager" + client.Create(ctx, cm) + _, err = ApplyClusterManager(ctx, client, cm) + if err != nil { + t.Errorf("applyClusterManager should not have returned error; err=%v", err) + } + + err = changeClusterManagerAnnotations(ctx, client, lm) + if err != nil { + t.Errorf("changeClusterManagerAnnotations should not have returned error=%v", err) + } + clusterManager := &enterpriseApi.ClusterManager{} + namespacedName = types.NamespacedName{ + Name: cm.Name, + Namespace: cm.Namespace, + } + err = client.Get(ctx, namespacedName, clusterManager) + if err != nil { + t.Errorf("changeClusterManagerAnnotations should not have returned error=%v", err) + } + + annotations := clusterManager.GetAnnotations() + if annotations["splunk/image-tag"] != lm.Spec.Image { + t.Errorf("changeClusterManagerAnnotations should have set the checkUpdateImage annotation field to the current image") + } +} + func TestClusterManagerWitReadyState(t *testing.T) { // create directory for app framework newpath := filepath.Join("/tmp", "appframework") @@ -1497,6 +1737,7 @@ func TestClusterManagerWitReadyState(t *testing.T) { // simulate create stateful set c.Create(ctx, statefulset) + clustermanager.Kind = "ClusterManager" // simulate create clustermanager instance before reconcilation c.Create(ctx, clustermanager) @@ -1510,6 +1751,12 @@ func TestClusterManagerWitReadyState(t *testing.T) { Namespace: clustermanager.Namespace, } + // cluster manager + err = c.Get(ctx, namespacedName, clustermanager) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + // simulate Ready state clustermanager.Status.Phase = enterpriseApi.PhaseReady clustermanager.Spec.ServiceTemplate.Annotations = map[string]string{ @@ -1536,6 +1783,7 @@ func TestClusterManagerWitReadyState(t *testing.T) { } // call reconciliation + clustermanager.Kind = "ClusterManager" _, err = ApplyClusterManager(ctx, c, clustermanager) if err != nil { t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) @@ -1654,6 +1902,7 @@ func TestClusterManagerWitReadyState(t *testing.T) { } // call reconciliation + clustermanager.Kind = "ClusterManager" _, err = ApplyClusterManager(ctx, c, clustermanager) if err != nil { t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) diff --git a/pkg/splunk/enterprise/clustermaster.go b/pkg/splunk/enterprise/clustermaster.go index 8782e49b3..ef746dfd1 100644 --- a/pkg/splunk/enterprise/clustermaster.go +++ b/pkg/splunk/enterprise/clustermaster.go @@ -48,6 +48,7 @@ func ApplyClusterMaster(ctx context.Context, client splcommon.ControllerClient, reqLogger := log.FromContext(ctx) scopedLog := reqLogger.WithName("ApplyClusterMaster") eventPublisher, _ := newK8EventPublisher(client, cr) + cr.Kind = "ClusterMaster" if cr.Status.ResourceRevMap == nil { cr.Status.ResourceRevMap = make(map[string]string) diff --git a/pkg/splunk/enterprise/clustermaster_test.go b/pkg/splunk/enterprise/clustermaster_test.go index 155570478..7472bbac0 100644 --- a/pkg/splunk/enterprise/clustermaster_test.go +++ b/pkg/splunk/enterprise/clustermaster_test.go @@ -159,18 +159,18 @@ func TestGetClusterMasterStatefulSet(t *testing.T) { configTester(t, "getClusterMasterStatefulSet", f, want) } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.LicenseManagerRef.Name = "stack1" cr.Spec.LicenseManagerRef.Namespace = "test" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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_LICENSE_MASTER_URL","value":"splunk-stack1-license-manager-service.test.svc.cluster.local"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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_LICENSE_MASTER_URL","value":"splunk-stack1-license-manager-service.test.svc.cluster.local"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.LicenseManagerRef.Name = "" cr.Spec.LicenseURL = "/mnt/splunk.lic" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"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_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.DefaultsURLApps = "/mnt/apps/apps.yml" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Create a serviceaccount current := corev1.ServiceAccount{ @@ -181,7 +181,7 @@ func TestGetClusterMasterStatefulSet(t *testing.T) { } _ = splutil.CreateResource(ctx, c, ¤t) cr.Spec.ServiceAccount = "defaults" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Add extraEnv cr.Spec.CommonSplunkSpec.ExtraEnv = []corev1.EnvVar{ @@ -190,7 +190,7 @@ func TestGetClusterMasterStatefulSet(t *testing.T) { Value: "test_value", }, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-cluster-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_cluster_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-cluster-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-cluster-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"cluster-master","app.kubernetes.io/part-of":"splunk-stack1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-cluster-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) } func TestApplyClusterMasterWithSmartstore(t *testing.T) { @@ -296,6 +296,7 @@ func TestApplyClusterMasterWithSmartstore(t *testing.T) { } // Without S3 keys, ApplyClusterManager should fail + current.Kind = "ClusterMaster" _, err := ApplyClusterMaster(ctx, client, ¤t) if err == nil { t.Errorf("ApplyClusterMaster should fail without S3 secrets configured") @@ -351,6 +352,7 @@ func TestApplyClusterMasterWithSmartstore(t *testing.T) { spltest.ReconcileTesterWithoutRedundantCheck(t, "TestApplyClusterMasterWithSmartstore-0", ¤t, revised, createCalls, updateCalls, reconcile, true, secret, &smartstoreConfigMap, ss, pod) + current.Kind = "ClusterMaster" current.Status.BundlePushTracker.NeedToPushMasterApps = true if _, err = ApplyClusterMaster(context.Background(), client, ¤t); err != nil { t.Errorf("ApplyClusterMaster() should not have returned error") @@ -572,6 +574,7 @@ func TestAppFrameworkApplyClusterMasterShouldNotFail(t *testing.T) { t.Errorf(err.Error()) } + cm.Kind = "ClusterMaster" _, err = ApplyClusterMaster(context.Background(), client, &cm) if err != nil { t.Errorf("ApplyClusterMaster should not have returned error here.") @@ -667,6 +670,7 @@ func TestApplyCLusterMasterDeletion(t *testing.T) { t.Errorf("Unable to create download directory for apps :%s", splcommon.AppDownloadVolume) } + cm.Kind = "ClusterMaster" _, err = ApplyClusterMaster(ctx, c, &cm) if err != nil { t.Errorf("ApplyClusterMaster should not have returned error here.") @@ -1220,7 +1224,11 @@ func TestClusterMasterWitReadyState(t *testing.T) { Name: clustermaster.Name, Namespace: clustermaster.Namespace, } - + err = c.Get(ctx, namespacedName, clustermaster) + if err != nil { + t.Errorf("Unexpected get cluster master %v", err) + debug.PrintStack() + } // simulate Ready state clustermaster.Status.Phase = enterpriseApi.PhaseReady clustermaster.Spec.ServiceTemplate.Annotations = map[string]string{ diff --git a/pkg/splunk/enterprise/configuration.go b/pkg/splunk/enterprise/configuration.go index 1b2677a59..12201e342 100644 --- a/pkg/splunk/enterprise/configuration.go +++ b/pkg/splunk/enterprise/configuration.go @@ -1009,6 +1009,7 @@ func updateSplunkPodTemplateWithConfig(ctx context.Context, client splcommon.Con env = removeDuplicateEnvVars(env) } + privileged := false // update each container in pod for idx := range podTemplateSpec.Spec.Containers { podTemplateSpec.Spec.Containers[idx].Resources = spec.Resources @@ -1016,6 +1017,23 @@ func updateSplunkPodTemplateWithConfig(ctx context.Context, client splcommon.Con podTemplateSpec.Spec.Containers[idx].ReadinessProbe = readinessProbe podTemplateSpec.Spec.Containers[idx].StartupProbe = startupProbe podTemplateSpec.Spec.Containers[idx].Env = env + podTemplateSpec.Spec.Containers[idx].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, + }, + } } } diff --git a/pkg/splunk/enterprise/events.go b/pkg/splunk/enterprise/events.go index f05917f18..ebdc13d62 100644 --- a/pkg/splunk/enterprise/events.go +++ b/pkg/splunk/enterprise/events.go @@ -55,12 +55,19 @@ func (k *K8EventPublisher) publishEvent(ctx context.Context, eventType, reason, // based on the custom resource instance type find name, type and create new event switch v := k.instance.(type) { case *enterpriseApi.Standalone: + event = v.NewEvent(eventType, reason, message) case *enterpriseApiV3.LicenseMaster: + event = v.NewEvent(eventType, reason, message) case *enterpriseApi.LicenseManager: + event = v.NewEvent(eventType, reason, message) case *enterpriseApi.IndexerCluster: + event = v.NewEvent(eventType, reason, message) case *enterpriseApi.ClusterManager: + event = v.NewEvent(eventType, reason, message) case *enterpriseApiV3.ClusterMaster: + event = v.NewEvent(eventType, reason, message) case *enterpriseApi.MonitoringConsole: + event = v.NewEvent(eventType, reason, message) case *enterpriseApi.SearchHeadCluster: event = v.NewEvent(eventType, reason, message) default: diff --git a/pkg/splunk/enterprise/indexercluster.go b/pkg/splunk/enterprise/indexercluster.go index c52528713..740cb3fac 100644 --- a/pkg/splunk/enterprise/indexercluster.go +++ b/pkg/splunk/enterprise/indexercluster.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "regexp" + "sort" "strconv" "strings" "time" @@ -55,6 +56,7 @@ func ApplyIndexerClusterManager(ctx context.Context, client splcommon.Controller reqLogger := log.FromContext(ctx) scopedLog := reqLogger.WithName("ApplyIndexerClusterManager").WithValues("name", cr.GetName(), "namespace", cr.GetNamespace()) eventPublisher, _ := newK8EventPublisher(client, cr) + cr.Kind = "IndexerCluster" // validate and updates defaults for CR err := validateIndexerClusterSpec(ctx, client, cr) @@ -93,7 +95,7 @@ func ApplyIndexerClusterManager(ctx context.Context, client splcommon.Controller Name: cr.Spec.ClusterManagerRef.Name, } managerIdxCluster := &enterpriseApi.ClusterManager{} - err = client.Get(context.TODO(), namespacedName, managerIdxCluster) + err = client.Get(ctx, namespacedName, managerIdxCluster) if err == nil { // when user creates both cluster manager and index cluster yaml file at the same time // cluser manager status is not yet set so it will be blank @@ -194,6 +196,13 @@ func ApplyIndexerClusterManager(ctx context.Context, client splcommon.Controller } } + // check if the IndexerCluster is ready for version upgrade + cr.Kind = "IndexerCluster" + continueReconcile, err := UpgradePathValidation(ctx, client, cr, cr.Spec.CommonSplunkSpec, &mgr) + if err != nil || !continueReconcile { + return result, err + } + // check if version upgrade is set if !versionUpgrade { phase, err = mgr.Update(ctx, client, statefulSet, cr.Spec.Replicas) @@ -205,7 +214,7 @@ func ApplyIndexerClusterManager(ctx context.Context, client splcommon.Controller // Delete the statefulset and recreate new one err = client.Delete(ctx, statefulSet) if err != nil { - eventPublisher.Warning(ctx, "UpdateManager", fmt.Sprintf("version mitmatch for indexer clustre and indexer container, delete statefulset failed %s", err.Error())) + eventPublisher.Warning(ctx, "UpdateManager", fmt.Sprintf("version mismatch for indexer cluster and indexer container, delete statefulset failed. Error=%s", err.Error())) eventPublisher.Warning(ctx, "UpdateManager", fmt.Sprintf("%s-%s, %s-%s", "indexer-image", cr.Spec.Image, "container-image", statefulSet.Spec.Template.Spec.Containers[0].Image)) return result, err } @@ -299,6 +308,7 @@ func ApplyIndexerCluster(ctx context.Context, client splcommon.ControllerClient, reqLogger := log.FromContext(ctx) scopedLog := reqLogger.WithName("ApplyIndexerCluster") eventPublisher, _ := newK8EventPublisher(client, cr) + cr.Kind = "IndexerCluster" // validate and updates defaults for CR err := validateIndexerClusterSpec(ctx, client, cr) @@ -337,7 +347,7 @@ func ApplyIndexerCluster(ctx context.Context, client splcommon.ControllerClient, Name: cr.Spec.ClusterMasterRef.Name, } managerIdxCluster := &enterpriseApiV3.ClusterMaster{} - err = client.Get(context.TODO(), namespacedName, managerIdxCluster) + err = client.Get(ctx, namespacedName, managerIdxCluster) if err == nil { // when user creates both cluster manager and index cluster yaml file at the same time // cluser master status is not yet set so it will be blank @@ -438,6 +448,13 @@ func ApplyIndexerCluster(ctx context.Context, client splcommon.ControllerClient, } } + // check if the IndexerCluster is ready for version upgrade + cr.Kind = "IndexerCluster" + continueReconcile, err := UpgradePathValidation(ctx, client, cr, cr.Spec.CommonSplunkSpec, &mgr) + if err != nil || !continueReconcile { + return result, err + } + // check if version upgrade is set if !versionUpgrade { phase, err = mgr.Update(ctx, client, statefulSet, cr.Spec.Replicas) @@ -939,6 +956,16 @@ func (mgr *indexerClusterPodManager) verifyRFPeers(ctx context.Context, c splcom return nil } +var GetClusterManagerInfoCall = func(ctx context.Context, mgr *indexerClusterPodManager) (*splclient.ClusterManagerInfo, error) { + c := mgr.getClusterManagerClient(ctx) + return c.GetClusterManagerInfo() +} + +var GetClusterManagerPeersCall = func(ctx context.Context, mgr *indexerClusterPodManager) (map[string]splclient.ClusterManagerPeerInfo, error) { + c := mgr.getClusterManagerClient(ctx) + return c.GetClusterManagerPeers() +} + // updateStatus for indexerClusterPodManager uses the REST API to update the status for an IndexerCluster custom resource func (mgr *indexerClusterPodManager) updateStatus(ctx context.Context, statefulSet *appsv1.StatefulSet) error { mgr.cr.Status.ReadyReplicas = statefulSet.Status.ReadyReplicas @@ -952,8 +979,7 @@ func (mgr *indexerClusterPodManager) updateStatus(ctx context.Context, statefulS } // get indexer cluster info from cluster manager if it's ready - c := mgr.getClusterManagerClient(ctx) - clusterInfo, err := c.GetClusterManagerInfo() + clusterInfo, err := GetClusterManagerInfoCall(ctx, mgr) if err != nil { return err } @@ -963,7 +989,7 @@ func (mgr *indexerClusterPodManager) updateStatus(ctx context.Context, statefulS mgr.cr.Status.MaintenanceMode = clusterInfo.MaintenanceMode // get peer information from cluster manager - peers, err := c.GetClusterManagerPeers() + peers, err := GetClusterManagerPeersCall(ctx, mgr) if err != nil { return err } @@ -1067,6 +1093,43 @@ func RetrieveCMSpec(ctx context.Context, client splcommon.ControllerClient, cr * return "", nil } +func getIndexerClusterSortedSiteList(ctx context.Context, c splcommon.ControllerClient, ref corev1.ObjectReference, indexerList enterpriseApi.IndexerClusterList) (enterpriseApi.IndexerClusterList, error) { + + namespaceList := enterpriseApi.IndexerClusterList{} + for _, v := range indexerList.Items { + if v.Spec.ClusterManagerRef == ref { + namespaceList.Items = append(namespaceList.Items, v) + } + } + + sort.SliceStable(namespaceList.Items, func(i, j int) bool { + return getSiteName(ctx, c, &namespaceList.Items[i]) < getSiteName(ctx, c, &namespaceList.Items[j]) + }) + + return namespaceList, nil +} + +func getSiteName(ctx context.Context, c splcommon.ControllerClient, cr *enterpriseApi.IndexerCluster) string { + defaults := cr.Spec.Defaults + // site name starts with site: + pattern := `site:\s+(\w+)` + + // Compile the regular expression pattern + re := regexp.MustCompile(pattern) + + // Find the first match in the input string + match := re.FindStringSubmatch(defaults) + + var extractedValue string + if len(match) > 1 { + // Extracted value is stored in the second element of the match array + extractedValue := match[1] + return extractedValue + } + + return extractedValue +} + // 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/indexercluster_test.go b/pkg/splunk/enterprise/indexercluster_test.go index 1eeda101b..70aba515a 100644 --- a/pkg/splunk/enterprise/indexercluster_test.go +++ b/pkg/splunk/enterprise/indexercluster_test.go @@ -735,7 +735,8 @@ func TestIndexerClusterPodManager(t *testing.T) { {MetaName: "*v1.StatefulSet-test-splunk-stack1"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, - {MetaName: "*v1.Pod-test-splunk-stack1-indexer-0"}, + //{MetaName: "*v1.Pod-test-splunk-stack1-indexer-0"}, + {MetaName: "*v1.Pod-test-splunk-manager1-cluster-manager-0"}, {MetaName: "*v1.Pod-test-splunk-manager1-cluster-manager-0"}, {MetaName: "*v1.Pod-test-splunk-stack1-0"}, } @@ -750,7 +751,7 @@ func TestIndexerClusterPodManager(t *testing.T) { listmockCall := []spltest.MockFuncCall{ {ListOpts: listOpts}} - wantCalls := map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[4], funcCalls[5]}, "Create": {funcCalls[1]}, "List": {listmockCall[0]}} + wantCalls := map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[4], funcCalls[4], funcCalls[5]}, "Create": {funcCalls[1]}, "List": {listmockCall[0]}} // test 1 ready pod mockHandlers := []spltest.MockHTTPHandler{ @@ -802,6 +803,7 @@ func TestIndexerClusterPodManager(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Pod-test-splunk-manager1-cluster-manager-0"}, + {MetaName: "*v1.Pod-test-splunk-manager1-cluster-manager-0"}, {MetaName: "*v1.Pod-test-splunk-stack1-0"}, {MetaName: "*v1.Pod-test-splunk-stack1-indexer-0"}, {MetaName: "*v1.Pod-test-splunk-stack1-indexer-0"}, @@ -815,6 +817,7 @@ func TestIndexerClusterPodManager(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Pod-test-splunk-manager1-cluster-manager-0"}, + {MetaName: "*v1.Pod-test-splunk-manager1-cluster-manager-0"}, {MetaName: "*v1.Pod-test-splunk-stack1-0"}, } mockHandlers = []spltest.MockHTTPHandler{mockHandlers[0], mockHandlers[1]} @@ -841,7 +844,7 @@ func TestIndexerClusterPodManager(t *testing.T) { statefulSet.Status.Replicas = 2 statefulSet.Status.ReadyReplicas = 2 statefulSet.Status.UpdatedReplicas = 2 - wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[4]}, "Create": {funcCalls[1]}} + wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[4], funcCalls[4]}, "Create": {funcCalls[1]}} method = "indexerClusterPodManager.Update(Pod Not Found)" indexerClusterPodManagerUpdateTester(t, method, mockHandlers, 1, enterpriseApi.PhaseScalingDown, statefulSet, wantCalls, nil, statefulSet, pod) @@ -864,6 +867,7 @@ func TestIndexerClusterPodManager(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Pod-test-splunk-manager1-cluster-manager-0"}, {MetaName: "*v1.Pod-test-splunk-manager1-cluster-manager-0"}, + {MetaName: "*v1.Pod-test-splunk-manager1-cluster-manager-0"}, {MetaName: "*v1.PersistentVolumeClaim-test-pvc-etc-splunk-stack1-1"}, {MetaName: "*v1.PersistentVolumeClaim-test-pvc-var-splunk-stack1-1"}, } @@ -1328,16 +1332,16 @@ func TestGetIndexerStatefulSet(t *testing.T) { } cr.Spec.Replicas = 0 - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.Replicas = 1 - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Define additional service port in CR and verified the statefulset has the new port cr.Spec.ServiceTemplate.Spec.Ports = []corev1.ServicePort{{Name: "user-defined", Port: 32000, Protocol: "UDP"}} - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Block moving DefaultsURLApps to SPLUNK_DEFAULTS_URL for indexer cluster member cr.Spec.DefaultsURLApps = "/mnt/apps/apps.yml" - test(` {"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Create a serviceaccount current := corev1.ServiceAccount{ @@ -1348,7 +1352,7 @@ func TestGetIndexerStatefulSet(t *testing.T) { } _ = splutil.CreateResource(ctx, c, ¤t) cr.Spec.ServiceAccount = "defaults" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Add extraEnv cr.Spec.CommonSplunkSpec.ExtraEnv = []corev1.EnvVar{ @@ -1357,7 +1361,7 @@ func TestGetIndexerStatefulSet(t *testing.T) { Value: "test_value", }, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-indexer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"},"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-stack1-indexer-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_CLUSTER_MASTER_URL","value":"splunk-manager1-cluster-manager-service"},{"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_indexer"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-indexer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"indexer","app.kubernetes.io/instance":"splunk-stack1-indexer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"indexer","app.kubernetes.io/part-of":"splunk-manager1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.ClusterManagerRef.Namespace = "other" if err := validateIndexerClusterSpec(ctx, c, &cr); err == nil { @@ -1576,7 +1580,11 @@ func TestIndexerClusterWithReadyState(t *testing.T) { Name: clustermanager.Name, Namespace: clustermanager.Namespace, } - + err := c.Get(ctx, namespacedName, clustermanager) + if err != nil { + t.Errorf("Unexpected get cluster manager %v", err) + debug.PrintStack() + } clustermanager.Status.Phase = enterpriseApi.PhaseReady clustermanager.Spec.ServiceTemplate.Annotations = map[string]string{ "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", @@ -1589,7 +1597,7 @@ func TestIndexerClusterWithReadyState(t *testing.T) { "app.kubernetes.io/name": "cluster-manager", "app.kubernetes.io/part-of": "splunk-test-cluster-manager", } - err := c.Status().Update(ctx, clustermanager) + err = c.Status().Update(ctx, clustermanager) if err != nil { t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) debug.PrintStack() @@ -1755,6 +1763,24 @@ func TestIndexerClusterWithReadyState(t *testing.T) { // simulate create clustermanager instance before reconcilation c.Create(ctx, indexercluster) + GetClusterInfoCall = func(ctx context.Context, mgr *indexerClusterPodManager, mockCall bool) (*splclient.ClusterInfo, error) { + cinfo := &splclient.ClusterInfo{ + MultiSite: "false", + } + return cinfo, nil + } + GetClusterManagerPeersCall = func(ctx context.Context, mgr *indexerClusterPodManager) (map[string]splclient.ClusterManagerPeerInfo, error) { + response := map[string]splclient.ClusterManagerPeerInfo{ + "splunk-test-indexer-0": { + ID: "site-1", + Status: "Up", + ActiveBundleID: "1", + BucketCount: 10, + Searchable: true, + }, + } + return response, err + } _, err = ApplyIndexerClusterManager(ctx, c, indexercluster) if err != nil { t.Errorf("Unexpected error while running reconciliation for indexer cluster %v", err) @@ -1765,7 +1791,11 @@ func TestIndexerClusterWithReadyState(t *testing.T) { Name: indexercluster.Name, Namespace: indexercluster.Namespace, } - + err = c.Get(ctx, namespacedName, indexercluster) + if err != nil { + t.Errorf("Unexpected get indexer cluster %v", err) + debug.PrintStack() + } // simulate Ready state indexercluster.Status.Phase = enterpriseApi.PhaseReady indexercluster.Spec.ServiceTemplate.Annotations = map[string]string{ diff --git a/pkg/splunk/enterprise/licensemanager.go b/pkg/splunk/enterprise/licensemanager.go index 83a1048dd..aa03a1b9c 100644 --- a/pkg/splunk/enterprise/licensemanager.go +++ b/pkg/splunk/enterprise/licensemanager.go @@ -46,6 +46,7 @@ func ApplyLicenseManager(ctx context.Context, client splcommon.ControllerClient, reqLogger := log.FromContext(ctx) scopedLog := reqLogger.WithName("ApplyLicenseManager") eventPublisher, _ := newK8EventPublisher(client, cr) + cr.Kind = "LicenseManager" // validate and updates defaults for CR err := validateLicenseManagerSpec(ctx, client, cr) @@ -172,12 +173,19 @@ func ApplyLicenseManager(ctx context.Context, client splcommon.ControllerClient, finalResult := handleAppFrameworkActivity(ctx, client, cr, &cr.Status.AppContext, &cr.Spec.AppFrameworkConfig) result = *finalResult + + // trigger ClusterManager reconcile by changing the splunk/image-tag annotation + err = changeClusterManagerAnnotations(ctx, client, cr) + if err != nil { + return result, err + } } // RequeueAfter if greater than 0, tells the Controller to requeue the reconcile key after the Duration. // Implies that Requeue is true, there is no need to set Requeue to true at the same time as RequeueAfter. if !result.Requeue { result.RequeueAfter = 0 } + return result, nil } diff --git a/pkg/splunk/enterprise/licensemanager_test.go b/pkg/splunk/enterprise/licensemanager_test.go index 78ad7c707..84e61661e 100644 --- a/pkg/splunk/enterprise/licensemanager_test.go +++ b/pkg/splunk/enterprise/licensemanager_test.go @@ -70,8 +70,8 @@ func TestApplyLicenseManager(t *testing.T) { client.MatchingLabels(labels), } listmockCall := []spltest.MockFuncCall{ - {ListOpts: listOpts}} - + {ListOpts: listOpts}, + } createCalls := map[string][]spltest.MockFuncCall{"Get": funcCalls, "Create": {funcCalls[0], funcCalls[3], funcCalls[6], funcCalls[8], funcCalls[10]}, "Update": {funcCalls[0]}, "List": {listmockCall[0]}} updateFuncCalls := []spltest.MockFuncCall{funcCalls[0], funcCalls[1], funcCalls[3], funcCalls[4], funcCalls[5], funcCalls[7], funcCalls[8], funcCalls[9], funcCalls[10], funcCalls[9], funcCalls[11], funcCalls[12]} updateCalls := map[string][]spltest.MockFuncCall{"Get": updateFuncCalls, "Update": {funcCalls[4]}, "List": {listmockCall[0]}} @@ -158,14 +158,14 @@ func TestGetLicenseManagerStatefulSet(t *testing.T) { configTester(t, "getLicenseManagerStatefulSet()", f, want) } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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_license_master"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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_license_master"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.LicenseURL = "/mnt/splunk.lic" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Allow installing apps via DefaultsURLApps for Licence Manager cr.Spec.DefaultsURLApps = "/mnt/apps/apps.yml" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Create a serviceaccount current := corev1.ServiceAccount{ @@ -176,7 +176,7 @@ func TestGetLicenseManagerStatefulSet(t *testing.T) { } _ = splutil.CreateResource(ctx, c, ¤t) cr.Spec.ServiceAccount = "defaults" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Add extraEnv cr.Spec.CommonSplunkSpec.ExtraEnv = []corev1.EnvVar{ @@ -185,7 +185,7 @@ func TestGetLicenseManagerStatefulSet(t *testing.T) { Value: "test_value", }, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-manager","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-manager-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-manager"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-manager","app.kubernetes.io/instance":"splunk-stack1-license-manager","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-manager","app.kubernetes.io/part-of":"splunk-stack1-license-manager"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-manager-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) } @@ -784,6 +784,11 @@ func TestLicenseManagerWithReadyState(t *testing.T) { return nil } + // Mock the addTelApp function for unit tests + addTelApp = func(ctx context.Context, podExecClient splutil.PodExecClientImpl, replicas int32, cr splcommon.MetaObject) error { + return nil + } + // create directory for app framework newpath := filepath.Join("/tmp", "appframework") _ = os.MkdirAll(newpath, os.ModePerm) @@ -835,31 +840,35 @@ func TestLicenseManagerWithReadyState(t *testing.T) { AppSources: appSourceSpec, } - // create clustermanager custom resource - clustermanager := &enterpriseApi.ClusterManager{ + // create license manager custom resource + + // create licensemanager custom resource + licensemanager := &enterpriseApi.LicenseManager{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "default", }, - Spec: enterpriseApi.ClusterManagerSpec{ + Spec: enterpriseApi.LicenseManagerSpec{ CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ Spec: enterpriseApi.Spec{ ImagePullPolicy: "Always", }, Volumes: []corev1.Volume{}, + MonitoringConsoleRef: corev1.ObjectReference{ + Name: "mcName", + }, }, - AppFrameworkConfig: appFrameworkSpec, }, } - creplicas := int32(1) - cstatefulset := &appsv1.StatefulSet{ + replicas := int32(1) + statefulset := &appsv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-cluster-manager", + Name: "splunk-test-license-manager", Namespace: "default", }, Spec: appsv1.StatefulSetSpec{ - ServiceName: "splunk-test-cluster-manager-headless", + ServiceName: "splunk-test-license-manager-headless", Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ Containers: []corev1.Container{ @@ -876,45 +885,80 @@ func TestLicenseManagerWithReadyState(t *testing.T) { }, }, }, - Replicas: &creplicas, + Replicas: &replicas, }, } + service := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "splunk-test-license-manager-headless", + Namespace: "default", + }, + } + + // simulate service + err := c.Create(ctx, service) + if err != nil { + t.Errorf("Unexpected create pod failed %v", err) + debug.PrintStack() + } + + // simulate create stateful set + err = c.Create(ctx, statefulset) + if err != nil { + t.Errorf("Unexpected create pod failed %v", err) + debug.PrintStack() + } + // simulate create clustermanager instance before reconcilation - c.Create(ctx, clustermanager) + err = c.Create(ctx, licensemanager) + if err != nil { + t.Errorf("Unexpected create pod failed %v", err) + debug.PrintStack() + } - // simulate Ready state - namespacedName := types.NamespacedName{ - Name: clustermanager.Name, - Namespace: clustermanager.Namespace, + _, err = ApplyLicenseManager(ctx, c, licensemanager) + if err != nil { + t.Errorf("Unexpected error while running reconciliation for indexer cluster %v", err) + debug.PrintStack() } - clustermanager.Status.Phase = enterpriseApi.PhaseReady - clustermanager.Spec.ServiceTemplate.Annotations = map[string]string{ + namespacedName := types.NamespacedName{ + Name: licensemanager.Name, + Namespace: licensemanager.Namespace, + } + err = c.Get(ctx, namespacedName, licensemanager) + if err != nil { + t.Errorf("Unexpected get license manager %v", err) + debug.PrintStack() + } + // simulate Ready state + licensemanager.Status.Phase = enterpriseApi.PhaseReady + licensemanager.Spec.ServiceTemplate.Annotations = map[string]string{ "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", "traffic.sidecar.istio.io/includeInboundPorts": "8000,8088", } - clustermanager.Spec.ServiceTemplate.Labels = map[string]string{ - "app.kubernetes.io/instance": "splunk-test-cluster-manager", + licensemanager.Spec.ServiceTemplate.Labels = map[string]string{ + "app.kubernetes.io/instance": "splunk-test-license-manager", "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/component": "cluster-manager", - "app.kubernetes.io/name": "cluster-manager", - "app.kubernetes.io/part-of": "splunk-test-cluster-manager", + "app.kubernetes.io/component": "license-manager", + "app.kubernetes.io/name": "license-manager", + "app.kubernetes.io/part-of": "splunk-test-license-manager", } - err := c.Status().Update(ctx, clustermanager) + err = c.Status().Update(ctx, licensemanager) if err != nil { t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) debug.PrintStack() } - err = c.Get(ctx, namespacedName, clustermanager) + err = c.Get(ctx, namespacedName, licensemanager) if err != nil { - t.Errorf("Unexpected get cluster manager %v", err) + t.Errorf("Unexpected get license manager %v", err) debug.PrintStack() } // call reconciliation - _, err = ApplyClusterManager(ctx, c, clustermanager) + _, err = ApplyLicenseManager(ctx, c, licensemanager) if err != nil { t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) debug.PrintStack() @@ -923,7 +967,7 @@ func TestLicenseManagerWithReadyState(t *testing.T) { // create pod stpod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-cluster-manager-0", + Name: "splunk-test-license-manager-0", Namespace: "default", }, Spec: corev1.PodSpec{ @@ -942,7 +986,7 @@ func TestLicenseManagerWithReadyState(t *testing.T) { }, } // simulate create stateful set - c.Create(ctx, stpod) + err = c.Create(ctx, stpod) if err != nil { t.Errorf("Unexpected create pod failed %v", err) debug.PrintStack() @@ -963,72 +1007,72 @@ func TestLicenseManagerWithReadyState(t *testing.T) { debug.PrintStack() } + // get latest stateful set stNamespacedName := types.NamespacedName{ - Name: "splunk-test-cluster-manager", + Name: "splunk-test-license-manager", Namespace: "default", } - err = c.Get(ctx, stNamespacedName, cstatefulset) + err = c.Get(ctx, stNamespacedName, statefulset) if err != nil { - t.Errorf("Unexpected get cluster manager %v", err) + t.Errorf("Unexpected get license manager %v", err) debug.PrintStack() } + // update statefulset - cstatefulset.Status.ReadyReplicas = 1 - cstatefulset.Status.Replicas = 1 - err = c.Status().Update(ctx, cstatefulset) + statefulset.Status.ReadyReplicas = 1 + statefulset.Status.Replicas = 1 + err = c.Status().Update(ctx, statefulset) if err != nil { t.Errorf("Unexpected update statefulset %v", err) debug.PrintStack() } - err = c.Get(ctx, namespacedName, clustermanager) + err = c.Get(ctx, namespacedName, licensemanager) if err != nil { - t.Errorf("Unexpected get cluster manager %v", err) + t.Errorf("Unexpected get license manager %v", err) debug.PrintStack() } // call reconciliation - _, err = ApplyClusterManager(ctx, c, clustermanager) + _, err = ApplyLicenseManager(ctx, c, licensemanager) if err != nil { t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) debug.PrintStack() } - clusterObjRef := corev1.ObjectReference{ - Kind: clustermanager.Kind, - Name: clustermanager.Name, - Namespace: clustermanager.Namespace, - UID: clustermanager.UID, + licenseObjRef := corev1.ObjectReference{ + Kind: licensemanager.Kind, + Name: licensemanager.Name, + Namespace: licensemanager.Namespace, + UID: licensemanager.UID, } - // create licensemanager custom resource - licensemanager := &enterpriseApi.LicenseManager{ + // create clustermanager custom resource + clustermanager := &enterpriseApi.ClusterManager{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "default", }, - Spec: enterpriseApi.LicenseManagerSpec{ + Spec: enterpriseApi.ClusterManagerSpec{ CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + LicenseManagerRef: licenseObjRef, Spec: enterpriseApi.Spec{ ImagePullPolicy: "Always", }, Volumes: []corev1.Volume{}, - MonitoringConsoleRef: corev1.ObjectReference{ - Name: "mcName", - }, - ClusterManagerRef: clusterObjRef, }, + AppFrameworkConfig: appFrameworkSpec, }, } - replicas := int32(1) - statefulset := &appsv1.StatefulSet{ + creplicas := int32(1) + cstatefulset := &appsv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-license-manager", + Name: "splunk-test-cluster-manager", Namespace: "default", }, Spec: appsv1.StatefulSetSpec{ - ServiceName: "splunk-test-license-manager-headless", + ServiceName: "splunk-test-cluster-manager-headless", Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ Containers: []corev1.Container{ @@ -1045,64 +1089,49 @@ func TestLicenseManagerWithReadyState(t *testing.T) { }, }, }, - Replicas: &replicas, - }, - } - - service := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-license-manager-headless", - Namespace: "default", + Replicas: &creplicas, }, } - // simulate service - c.Create(ctx, service) - - // simulate create stateful set - c.Create(ctx, statefulset) - // simulate create clustermanager instance before reconcilation - c.Create(ctx, licensemanager) - - _, err = ApplyLicenseManager(ctx, c, licensemanager) + err = c.Create(ctx, clustermanager) if err != nil { - t.Errorf("Unexpected error while running reconciliation for indexer cluster %v", err) + t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) debug.PrintStack() } + // simulate Ready state namespacedName = types.NamespacedName{ - Name: licensemanager.Name, - Namespace: licensemanager.Namespace, + Name: clustermanager.Name, + Namespace: clustermanager.Namespace, } - // simulate Ready state - licensemanager.Status.Phase = enterpriseApi.PhaseReady - licensemanager.Spec.ServiceTemplate.Annotations = map[string]string{ + clustermanager.Status.Phase = enterpriseApi.PhaseReady + clustermanager.Spec.ServiceTemplate.Annotations = map[string]string{ "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", "traffic.sidecar.istio.io/includeInboundPorts": "8000,8088", } - licensemanager.Spec.ServiceTemplate.Labels = map[string]string{ - "app.kubernetes.io/instance": "splunk-test-license-manager", + clustermanager.Spec.ServiceTemplate.Labels = map[string]string{ + "app.kubernetes.io/instance": "splunk-test-cluster-manager", "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/component": "license-manager", - "app.kubernetes.io/name": "license-manager", - "app.kubernetes.io/part-of": "splunk-test-license-manager", + "app.kubernetes.io/component": "cluster-manager", + "app.kubernetes.io/name": "cluster-manager", + "app.kubernetes.io/part-of": "splunk-test-cluster-manager", } - err = c.Status().Update(ctx, licensemanager) + err = c.Status().Update(ctx, clustermanager) if err != nil { t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) debug.PrintStack() } - err = c.Get(ctx, namespacedName, licensemanager) + err = c.Get(ctx, namespacedName, clustermanager) if err != nil { - t.Errorf("Unexpected get license manager %v", err) + t.Errorf("Unexpected get cluster manager %v", err) debug.PrintStack() } // call reconciliation - _, err = ApplyLicenseManager(ctx, c, licensemanager) + _, err = ApplyClusterManager(ctx, c, clustermanager) if err != nil { t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) debug.PrintStack() @@ -1111,7 +1140,7 @@ func TestLicenseManagerWithReadyState(t *testing.T) { // create pod stpod = &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-license-manager-0", + Name: "splunk-test-cluster-manager-0", Namespace: "default", }, Spec: corev1.PodSpec{ @@ -1130,7 +1159,7 @@ func TestLicenseManagerWithReadyState(t *testing.T) { }, } // simulate create stateful set - c.Create(ctx, stpod) + err = c.Create(ctx, stpod) if err != nil { t.Errorf("Unexpected create pod failed %v", err) debug.PrintStack() @@ -1151,40 +1180,45 @@ func TestLicenseManagerWithReadyState(t *testing.T) { debug.PrintStack() } - // get latest stateful set stNamespacedName = types.NamespacedName{ - Name: "splunk-test-license-manager", + Name: "splunk-test-cluster-manager", Namespace: "default", } - err = c.Get(ctx, stNamespacedName, statefulset) + err = c.Get(ctx, stNamespacedName, cstatefulset) if err != nil { - t.Errorf("Unexpected get license manager %v", err) + t.Errorf("Unexpected get cluster manager %v", err) debug.PrintStack() } - // update statefulset - statefulset.Status.ReadyReplicas = 1 - statefulset.Status.Replicas = 1 - err = c.Status().Update(ctx, statefulset) + cstatefulset.Status.ReadyReplicas = 1 + cstatefulset.Status.Replicas = 1 + err = c.Status().Update(ctx, cstatefulset) if err != nil { t.Errorf("Unexpected update statefulset %v", err) debug.PrintStack() } - err = c.Get(ctx, namespacedName, licensemanager) + err = c.Get(ctx, namespacedName, clustermanager) if err != nil { - t.Errorf("Unexpected get license manager %v", err) + t.Errorf("Unexpected get cluster manager %v", err) + debug.PrintStack() + } + + // call reconciliation + _, err = ApplyClusterManager(ctx, c, clustermanager) + if err != nil { + t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) debug.PrintStack() } //create namespace MC statefulset current := appsv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-default-monitoring-console", + Name: "splunk-default-license-manager", Namespace: "default", }, } - namespacedName = types.NamespacedName{Namespace: "default", Name: "splunk-default-monitoring-console"} + namespacedName = types.NamespacedName{Namespace: "default", Name: "splunk-default-license-manager"} // Create MC statefulset err = splutil.CreateResource(ctx, c, ¤t) @@ -1205,7 +1239,7 @@ func TestLicenseManagerWithReadyState(t *testing.T) { configmap := corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-default-monitoring-console", + Name: "splunk-default-license-manager", Namespace: "default", }, } diff --git a/pkg/splunk/enterprise/licensemaster_test.go b/pkg/splunk/enterprise/licensemaster_test.go index 6b9af0dc4..f479e50ce 100644 --- a/pkg/splunk/enterprise/licensemaster_test.go +++ b/pkg/splunk/enterprise/licensemaster_test.go @@ -174,12 +174,12 @@ func TestGetLicenseMasterStatefulSet(t *testing.T) { configTester(t, "getLicenseMasterStatefulSet()", f, want) } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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_license_master"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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_license_master"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.LicenseURL = "/mnt/splunk.lic" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Allow installing apps via DefaultsURLApps for Licence Manager cr.Spec.DefaultsURLApps = "/mnt/apps/apps.yml" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Create a serviceaccount current := corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ @@ -189,7 +189,7 @@ func TestGetLicenseMasterStatefulSet(t *testing.T) { } _ = splutil.CreateResource(ctx, c, ¤t) cr.Spec.ServiceAccount = "defaults" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Add extraEnv cr.Spec.CommonSplunkSpec.ExtraEnv = []corev1.EnvVar{ { @@ -197,7 +197,7 @@ func TestGetLicenseMasterStatefulSet(t *testing.T) { Value: "test_value", }, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-license-master","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"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/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_license_master"},{"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_LICENSE_URI","value":"/mnt/splunk.lic"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-license-master"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"license-master","app.kubernetes.io/instance":"splunk-stack1-license-master","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"license-master","app.kubernetes.io/part-of":"splunk-stack1-license-master"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-license-master-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) } func TestAppFrameworkApplyLicenseMasterShouldNotFail(t *testing.T) { @@ -784,8 +784,8 @@ func TestLicenseMasterWithReadyState(t *testing.T) { response1, _ := json.Marshal(apiResponse1) response2, _ := json.Marshal(apiResponse2) - wantRequest1, _ := http.NewRequest("GET", "https://splunk-test-cluster-manager-service.default.svc.cluster.local:8089/services/cluster/manager/info?count=0&output_mode=json", nil) - wantRequest2, _ := http.NewRequest("GET", "https://splunk-test-cluster-manager-service.default.svc.cluster.local:8089/services/cluster/manager/peers?count=0&output_mode=json", nil) + wantRequest1, _ := http.NewRequest("GET", "https://splunk-test-cluster-master-service.default.svc.cluster.local:8089/services/cluster/manager/info?count=0&output_mode=json", nil) + wantRequest2, _ := http.NewRequest("GET", "https://splunk-test-cluster-master-service.default.svc.cluster.local:8089/services/cluster/manager/peers?count=0&output_mode=json", nil) mclient.AddHandler(wantRequest1, 200, string(response1), nil) mclient.AddHandler(wantRequest2, 200, string(response2), nil) @@ -807,6 +807,7 @@ func TestLicenseMasterWithReadyState(t *testing.T) { builder := fake.NewClientBuilder() c := builder.Build() utilruntime.Must(enterpriseApiV3.AddToScheme(clientgoscheme.Scheme)) + utilruntime.Must(enterpriseApi.AddToScheme(clientgoscheme.Scheme)) ctx := context.TODO() // Create App framework volume @@ -845,31 +846,38 @@ func TestLicenseMasterWithReadyState(t *testing.T) { AppSources: appSourceSpec, } - // create clustermanager custom resource - clustermanager := &enterpriseApi.ClusterManager{ + // Mock the addTelApp function for unit tests + addTelApp = func(ctx context.Context, podExecClient splutil.PodExecClientImpl, replicas int32, cr splcommon.MetaObject) error { + return nil + } + + // create licensemaster custom resource + licensemaster := &enterpriseApiV3.LicenseMaster{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "default", }, - Spec: enterpriseApi.ClusterManagerSpec{ + Spec: enterpriseApiV3.LicenseMasterSpec{ CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ Spec: enterpriseApi.Spec{ ImagePullPolicy: "Always", }, Volumes: []corev1.Volume{}, + MonitoringConsoleRef: corev1.ObjectReference{ + Name: "mcName", + }, }, - AppFrameworkConfig: appFrameworkSpec, }, } - creplicas := int32(1) - cstatefulset := &appsv1.StatefulSet{ + replicas := int32(1) + statefulset := &appsv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-cluster-manager", + Name: "splunk-test-license-master", Namespace: "default", }, Spec: appsv1.StatefulSetSpec{ - ServiceName: "splunk-test-cluster-manager-headless", + ServiceName: "splunk-test-license-master-headless", Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ Containers: []corev1.Container{ @@ -886,54 +894,84 @@ func TestLicenseMasterWithReadyState(t *testing.T) { }, }, }, - Replicas: &creplicas, + Replicas: &replicas, + }, + } + + service := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "splunk-test-license-master-headless", + Namespace: "default", }, } + // simulate service + err := c.Create(ctx, service) + if err != nil { + t.Errorf("Unexpected error while running reconciliation for indexer cluster %v", err) + debug.PrintStack() + } + + // simulate create stateful set + err = c.Create(ctx, statefulset) + if err != nil { + t.Errorf("Unexpected error while running reconciliation for indexer cluster %v", err) + debug.PrintStack() + } + // simulate create clustermanager instance before reconcilation - c.Create(ctx, clustermanager) + err = c.Create(ctx, licensemaster) + if err != nil { + t.Errorf("Unexpected error while running reconciliation for indexer cluster %v", err) + debug.PrintStack() + } + _, err = ApplyLicenseMaster(ctx, c, licensemaster) + if err != nil { + t.Errorf("Unexpected error while running reconciliation for indexer cluster %v", err) + debug.PrintStack() + } - // simulate Ready state namespacedName := types.NamespacedName{ - Name: clustermanager.Name, - Namespace: clustermanager.Namespace, + Name: licensemaster.Name, + Namespace: licensemaster.Namespace, } - clustermanager.Status.Phase = enterpriseApi.PhaseReady - clustermanager.Spec.ServiceTemplate.Annotations = map[string]string{ + // simulate Ready state + licensemaster.Status.Phase = enterpriseApi.PhaseReady + licensemaster.Spec.ServiceTemplate.Annotations = map[string]string{ "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", "traffic.sidecar.istio.io/includeInboundPorts": "8000,8088", } - clustermanager.Spec.ServiceTemplate.Labels = map[string]string{ - "app.kubernetes.io/instance": "splunk-test-cluster-manager", + licensemaster.Spec.ServiceTemplate.Labels = map[string]string{ + "app.kubernetes.io/instance": "splunk-test-license-master", "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/component": "cluster-manager", - "app.kubernetes.io/name": "cluster-manager", - "app.kubernetes.io/part-of": "splunk-test-cluster-manager", + "app.kubernetes.io/component": "license-master", + "app.kubernetes.io/name": "license-master", + "app.kubernetes.io/part-of": "splunk-test-license-master", } - err := c.Status().Update(ctx, clustermanager) + err = c.Status().Update(ctx, licensemaster) if err != nil { - t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) + t.Errorf("Unexpected error while running reconciliation for cluster master with app framework %v", err) debug.PrintStack() } - err = c.Get(ctx, namespacedName, clustermanager) + err = c.Get(ctx, namespacedName, licensemaster) if err != nil { - t.Errorf("Unexpected get cluster manager %v", err) + t.Errorf("Unexpected get license manager %v", err) debug.PrintStack() } // call reconciliation - _, err = ApplyClusterManager(ctx, c, clustermanager) + _, err = ApplyLicenseMaster(ctx, c, licensemaster) if err != nil { - t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) + t.Errorf("Unexpected error while running reconciliation for cluster master with app framework %v", err) debug.PrintStack() } // create pod stpod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-cluster-manager-0", + Name: "splunk-test-license-master-0", Namespace: "default", }, Spec: corev1.PodSpec{ @@ -973,77 +1011,72 @@ func TestLicenseMasterWithReadyState(t *testing.T) { debug.PrintStack() } + // get latest stateful set stNamespacedName := types.NamespacedName{ - Name: "splunk-test-cluster-manager", + Name: "splunk-test-license-master", Namespace: "default", } - err = c.Get(ctx, stNamespacedName, cstatefulset) + err = c.Get(ctx, stNamespacedName, statefulset) if err != nil { - t.Errorf("Unexpected get cluster manager %v", err) + t.Errorf("Unexpected get license manager %v", err) debug.PrintStack() } + // update statefulset - cstatefulset.Status.ReadyReplicas = 1 - cstatefulset.Status.Replicas = 1 - err = c.Status().Update(ctx, cstatefulset) + statefulset.Status.ReadyReplicas = 1 + statefulset.Status.Replicas = 1 + err = c.Status().Update(ctx, statefulset) if err != nil { t.Errorf("Unexpected update statefulset %v", err) debug.PrintStack() } - err = c.Get(ctx, namespacedName, clustermanager) + err = c.Get(ctx, namespacedName, licensemaster) if err != nil { - t.Errorf("Unexpected get cluster manager %v", err) + t.Errorf("Unexpected get license manager %v", err) debug.PrintStack() } - // Mock the addTelApp function for unit tests - addTelApp = func(ctx context.Context, podExecClient splutil.PodExecClientImpl, replicas int32, cr splcommon.MetaObject) error { - return nil - } - - // call reconciliation - _, err = ApplyClusterManager(ctx, c, clustermanager) - if err != nil { - t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) - debug.PrintStack() + //create namespace MC statefulset + current := appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "splunk-default-license-master", + Namespace: "default", + }, } - clusterObjRef := corev1.ObjectReference{ - Kind: clustermanager.Kind, - Name: clustermanager.Name, - Namespace: clustermanager.Namespace, - UID: clustermanager.UID, + licenseObjRef := corev1.ObjectReference{ + Kind: licensemaster.Kind, + Name: licensemaster.Name, + Namespace: licensemaster.Namespace, + UID: licensemaster.UID, } - - // create licensemaster custom resource - licensemaster := &enterpriseApiV3.LicenseMaster{ + // create clustermanager custom resource + clustermanager := &enterpriseApiV3.ClusterMaster{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "default", }, - Spec: enterpriseApiV3.LicenseMasterSpec{ + Spec: enterpriseApiV3.ClusterMasterSpec{ CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + LicenseMasterRef: licenseObjRef, Spec: enterpriseApi.Spec{ ImagePullPolicy: "Always", }, Volumes: []corev1.Volume{}, - MonitoringConsoleRef: corev1.ObjectReference{ - Name: "mcName", - }, - ClusterManagerRef: clusterObjRef, }, + AppFrameworkConfig: appFrameworkSpec, }, } - replicas := int32(1) - statefulset := &appsv1.StatefulSet{ + creplicas := int32(1) + cstatefulset := &appsv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-license-master", + Name: "splunk-test-cluster-master", Namespace: "default", }, Spec: appsv1.StatefulSetSpec{ - ServiceName: "splunk-test-license-master-headless", + ServiceName: "splunk-test-cluster-master-headless", Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ Containers: []corev1.Container{ @@ -1060,73 +1093,59 @@ func TestLicenseMasterWithReadyState(t *testing.T) { }, }, }, - Replicas: &replicas, - }, - } - - service := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-license-master-headless", - Namespace: "default", + Replicas: &creplicas, }, } - - // simulate service - c.Create(ctx, service) - - // simulate create stateful set - c.Create(ctx, statefulset) + clustermanager.Kind = "ClusterManager" // simulate create clustermanager instance before reconcilation - c.Create(ctx, licensemaster) - - _, err = ApplyLicenseMaster(ctx, c, licensemaster) + err = c.Create(ctx, clustermanager) if err != nil { - t.Errorf("Unexpected error while running reconciliation for indexer cluster %v", err) + t.Errorf("Unexpected error while running reconciliation for cluster master with app framework %v", err) debug.PrintStack() } - + // simulate Ready state namespacedName = types.NamespacedName{ - Name: licensemaster.Name, - Namespace: licensemaster.Namespace, + Name: clustermanager.Name, + Namespace: clustermanager.Namespace, } - // simulate Ready state - licensemaster.Status.Phase = enterpriseApi.PhaseReady - licensemaster.Spec.ServiceTemplate.Annotations = map[string]string{ + clustermanager.Status.Phase = enterpriseApi.PhaseReady + clustermanager.Spec.ServiceTemplate.Annotations = map[string]string{ "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", "traffic.sidecar.istio.io/includeInboundPorts": "8000,8088", } - licensemaster.Spec.ServiceTemplate.Labels = map[string]string{ - "app.kubernetes.io/instance": "splunk-test-license-master", + clustermanager.Spec.ServiceTemplate.Labels = map[string]string{ + "app.kubernetes.io/instance": "splunk-test-cluster-master", "app.kubernetes.io/managed-by": "splunk-operator", - "app.kubernetes.io/component": "license-master", - "app.kubernetes.io/name": "license-master", - "app.kubernetes.io/part-of": "splunk-test-license-master", + "app.kubernetes.io/component": "cluster-master", + "app.kubernetes.io/name": "cluster-master", + "app.kubernetes.io/part-of": "splunk-test-cluster-master", } - err = c.Status().Update(ctx, licensemaster) + clustermanager.Kind = "ClusterManager" + err = c.Status().Update(ctx, clustermanager) if err != nil { - t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) + t.Errorf("Unexpected error while running reconciliation for cluster master with app framework %v", err) debug.PrintStack() } - err = c.Get(ctx, namespacedName, licensemaster) + err = c.Get(ctx, namespacedName, clustermanager) if err != nil { - t.Errorf("Unexpected get license manager %v", err) + t.Errorf("Unexpected get cluster master %v", err) debug.PrintStack() } // call reconciliation - _, err = ApplyLicenseMaster(ctx, c, licensemaster) + _, err = ApplyClusterMaster(ctx, c, clustermanager) if err != nil { - t.Errorf("Unexpected error while running reconciliation for cluster manager with app framework %v", err) + t.Errorf("Unexpected error while running reconciliation for cluster master with app framework %v", err) debug.PrintStack() } // create pod stpod = &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-test-license-master-0", + Name: "splunk-test-cluster-master-0", Namespace: "default", }, Spec: corev1.PodSpec{ @@ -1166,56 +1185,52 @@ func TestLicenseMasterWithReadyState(t *testing.T) { debug.PrintStack() } - // get latest stateful set stNamespacedName = types.NamespacedName{ - Name: "splunk-test-license-master", + Name: "splunk-test-cluster-master", Namespace: "default", } - err = c.Get(ctx, stNamespacedName, statefulset) + err = c.Get(ctx, stNamespacedName, cstatefulset) if err != nil { - t.Errorf("Unexpected get license manager %v", err) + t.Errorf("Unexpected get cluster master %v", err) debug.PrintStack() } - // update statefulset - statefulset.Status.ReadyReplicas = 1 - statefulset.Status.Replicas = 1 - err = c.Status().Update(ctx, statefulset) + cstatefulset.Status.ReadyReplicas = 1 + cstatefulset.Status.Replicas = 1 + err = c.Status().Update(ctx, cstatefulset) if err != nil { t.Errorf("Unexpected update statefulset %v", err) debug.PrintStack() } - err = c.Get(ctx, namespacedName, licensemaster) + err = c.Get(ctx, namespacedName, clustermanager) if err != nil { - t.Errorf("Unexpected get license manager %v", err) + t.Errorf("Unexpected get cluster master %v", err) debug.PrintStack() } - //create namespace MC statefulset - current := appsv1.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: "splunk-default-monitoring-console", - Namespace: "default", - }, + // call reconciliation + _, err = ApplyClusterMaster(ctx, c, clustermanager) + if err != nil { + t.Errorf("Unexpected error while running reconciliation for cluster master with app framework %v", err) + debug.PrintStack() } - namespacedName = types.NamespacedName{Namespace: "default", Name: "splunk-default-monitoring-console"} - // Create MC statefulset + // Create License master statefulset err = splutil.CreateResource(ctx, c, ¤t) if err != nil { - t.Errorf("Failed to create owner reference %s", current.GetName()) + t.Errorf("Failed to create owner reference %s", err) } - + namespacedName = types.NamespacedName{Namespace: "default", Name: "splunk-default-license-master"} //setownerReference err = splctrl.SetStatefulSetOwnerRef(ctx, c, licensemaster, namespacedName) if err != nil { - t.Errorf("Couldn't set owner ref for resource %s", current.GetName()) + t.Errorf("Couldn't set owner ref for resource %s ", err) } err = c.Get(ctx, namespacedName, ¤t) if err != nil { - t.Errorf("Couldn't get the statefulset resource %s", current.GetName()) + t.Errorf("Couldn't get the statefulset resource %s", err) } configmap := corev1.ConfigMap{ diff --git a/pkg/splunk/enterprise/monitoringconsole.go b/pkg/splunk/enterprise/monitoringconsole.go index 8979877de..7bedf70a0 100644 --- a/pkg/splunk/enterprise/monitoringconsole.go +++ b/pkg/splunk/enterprise/monitoringconsole.go @@ -34,6 +34,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + rclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -49,6 +50,7 @@ func ApplyMonitoringConsole(ctx context.Context, client splcommon.ControllerClie reqLogger := log.FromContext(ctx) scopedLog := reqLogger.WithName("ApplyMonitoringConsole") eventPublisher, _ := newK8EventPublisher(client, cr) + cr.Kind = "MonitoringConsole" if cr.Status.ResourceRevMap == nil { cr.Status.ResourceRevMap = make(map[string]string) @@ -136,6 +138,12 @@ func ApplyMonitoringConsole(ctx context.Context, client splcommon.ControllerClie return result, err } + // check if the Monitoring Console is ready for version upgrade, if required + continueReconcile, err := UpgradePathValidation(ctx, client, cr, cr.Spec.CommonSplunkSpec, nil) + if err != nil || !continueReconcile { + return result, err + } + mgr := splctrl.DefaultStatefulSetPodManager{} phase, err := mgr.Update(ctx, client, statefulSet, 1) if err != nil { @@ -148,6 +156,7 @@ func ApplyMonitoringConsole(ctx context.Context, client splcommon.ControllerClie if cr.Status.Phase == enterpriseApi.PhaseReady { finalResult := handleAppFrameworkActivity(ctx, client, cr, &cr.Status.AppContext, &cr.Spec.AppFrameworkConfig) result = *finalResult + } // RequeueAfter if greater than 0, tells the Controller to requeue the reconcile key after the Duration. // Implies that Requeue is true, there is no need to set Requeue to true at the same time as RequeueAfter. @@ -355,3 +364,70 @@ func DeleteURLsConfigMap(revised *corev1.ConfigMap, crName string, newURLs []cor } } } + +// changeMonitoringConsoleAnnotations updates the splunk/image-tag field of the MonitoringConsole annotations to trigger the reconcile loop +// on update, and returns error if something is wrong. +func changeMonitoringConsoleAnnotations(ctx context.Context, client splcommon.ControllerClient, cr *enterpriseApi.ClusterManager) error { + reqLogger := log.FromContext(ctx) + scopedLog := reqLogger.WithName("changeMonitoringConsoleAnnotations").WithValues("name", cr.GetName(), "namespace", cr.GetNamespace()) + eventPublisher, _ := newK8EventPublisher(client, cr) + + monitoringConsoleInstance := &enterpriseApi.MonitoringConsole{} + if len(cr.Spec.MonitoringConsoleRef.Name) > 0 { + // if the ClusterManager holds the MonitoringConsoleRef + namespacedName := types.NamespacedName{ + Namespace: cr.GetNamespace(), + Name: cr.Spec.MonitoringConsoleRef.Name, + } + err := client.Get(ctx, namespacedName, monitoringConsoleInstance) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil + } + return err + } + } else { + // List out all the MonitoringConsole instances in the namespace + opts := []rclient.ListOption{ + rclient.InNamespace(cr.GetNamespace()), + } + objectList := enterpriseApi.MonitoringConsoleList{} + err := client.List(ctx, &objectList, opts...) + if err != nil { + if err.Error() == "NotFound" { + return nil + } + return err + } + if len(objectList.Items) == 0 { + return nil + } + + // check if instance has the required ClusterManagerRef + for _, mc := range objectList.Items { + if mc.Spec.ClusterManagerRef.Name == cr.GetName() { + monitoringConsoleInstance = &mc + break + } + } + + if len(monitoringConsoleInstance.GetName()) == 0 { + return nil + } + } + + image, err := getCurrentImage(ctx, client, cr, SplunkClusterManager) + if err != nil { + eventPublisher.Warning(ctx, "changeMonitoringConsoleAnnotations", fmt.Sprintf("Could not get the ClusterManager Image. Reason %v", err)) + scopedLog.Error(err, "Get ClusterManager Image failed with", "error", err) + return err + } + err = changeAnnotations(ctx, client, image, monitoringConsoleInstance) + if err != nil { + eventPublisher.Warning(ctx, "changeMonitoringConsoleAnnotations", fmt.Sprintf("Could not update annotations. Reason %v", err)) + scopedLog.Error(err, "MonitoringConsole types update after changing annotations failed with", "error", err) + return err + } + + return nil +} diff --git a/pkg/splunk/enterprise/monitoringconsole_test.go b/pkg/splunk/enterprise/monitoringconsole_test.go index 89ab4cf3a..91f130853 100644 --- a/pkg/splunk/enterprise/monitoringconsole_test.go +++ b/pkg/splunk/enterprise/monitoringconsole_test.go @@ -72,6 +72,7 @@ func TestApplyMonitoringConsole(t *testing.T) { {MetaName: "*v1.ConfigMap-test-splunk-stack1-monitoring-console"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-monitoring-console"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-monitoring-console"}, + {MetaName: "*v1.StatefulSet-test-splunk-stack1-monitoring-console"}, {MetaName: "*v4.MonitoringConsole-test-stack1"}, {MetaName: "*v4.MonitoringConsole-test-stack1"}, } @@ -81,15 +82,19 @@ func TestApplyMonitoringConsole(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Service-test-splunk-stack1-monitoring-console-headless"}, {MetaName: "*v1.Service-test-splunk-stack1-monitoring-console-service"}, + {MetaName: "*v1.StatefulSet-test-splunk-stack1-monitoring-console"}, {MetaName: "*v1.ConfigMap-test-splunk-test-probe-configmap"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-stack1-monitoring-console-secret-v1"}, + {MetaName: "*v1.ConfigMap-test-splunk-stack1-monitoring-console"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-monitoring-console"}, {MetaName: "*v1.ConfigMap-test-splunk-stack1-monitoring-console"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-monitoring-console"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-monitoring-console"}, + {MetaName: "*v1.StatefulSet-test-splunk-stack1-monitoring-console"}, + {MetaName: "*v4.MonitoringConsole-test-stack1"}, {MetaName: "*v4.MonitoringConsole-test-stack1"}, } @@ -365,11 +370,11 @@ func TestGetMonitoringConsoleStatefulSet(t *testing.T) { configTester(t, "getMonitoringConsoleStatefulSet()", f, want) } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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-stack1-monitoring-console-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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"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_monitor"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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-stack1-monitoring-console-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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"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_monitor"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.EtcVolumeStorageConfig.EphemeralStorage = true cr.Spec.VarVolumeStorageConfig.EphemeralStorage = true - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"mnt-splunk-etc","emptyDir":{}},{"name":"mnt-splunk-var","emptyDir":{}},{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"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_monitor"},{"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"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"mnt-splunk-etc","mountPath":"/opt/splunk/etc"},{"name":"mnt-splunk-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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"mnt-splunk-etc","emptyDir":{}},{"name":"mnt-splunk-var","emptyDir":{}},{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"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_monitor"},{"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"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"mnt-splunk-etc","mountPath":"/opt/splunk/etc"},{"name":"mnt-splunk-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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.EtcVolumeStorageConfig.EphemeralStorage = false cr.Spec.VarVolumeStorageConfig.EphemeralStorage = false @@ -383,10 +388,10 @@ func TestGetMonitoringConsoleStatefulSet(t *testing.T) { cr.Spec.Volumes = []corev1.Volume{ {Name: "defaults"}, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-monitoring-console-defaults","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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_monitor"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-monitoring-console-defaults","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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_monitor"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.DefaultsURLApps = "/mnt/apps/apps.yml" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-monitoring-console-defaults","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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_monitor"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-monitoring-console-defaults","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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_monitor"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Create a serviceaccount current := corev1.ServiceAccount{ @@ -397,7 +402,7 @@ func TestGetMonitoringConsoleStatefulSet(t *testing.T) { } _ = splutil.CreateResource(ctx, c, ¤t) cr.Spec.ServiceAccount = "defaults" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-monitoring-console-defaults","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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_monitor"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-monitoring-console-defaults","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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_monitor"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Add extraEnv cr.Spec.CommonSplunkSpec.ExtraEnv = []corev1.EnvVar{ @@ -406,7 +411,7 @@ func TestGetMonitoringConsoleStatefulSet(t *testing.T) { Value: "test_value", }, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-monitoring-console-defaults","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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_monitor"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-monitoring-console","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"},"annotations":{"monitoringConsoleConfigRev":"","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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-monitoring-console-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-monitoring-console-defaults","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"}],"envFrom":[{"configMapRef":{"name":"splunk-stack1-monitoring-console"}}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_monitor"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-monitoring-console"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"monitoring-console","app.kubernetes.io/instance":"splunk-stack1-monitoring-console","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"monitoring-console","app.kubernetes.io/part-of":"splunk-stack1-monitoring-console"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-monitoring-console-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) } func TestAppFrameworkApplyMonitoringConsoleShouldNotFail(t *testing.T) { @@ -875,7 +880,11 @@ func TestMonitoringConsoleWithReadyState(t *testing.T) { Name: monitoringconsole.Name, Namespace: monitoringconsole.Namespace, } - + err = c.Get(ctx, namespacedName, monitoringconsole) + if err != nil { + t.Errorf("Unexpected get monitoring console. Error = %v", err) + debug.PrintStack() + } // simulate Ready state monitoringconsole.Status.Phase = enterpriseApi.PhaseReady monitoringconsole.Spec.ServiceTemplate.Annotations = map[string]string{ @@ -1100,3 +1109,91 @@ func TestGetMonitoringConsoleList(t *testing.T) { t.Errorf("Got wrong number of IndexerCluster objects. Expected=%d, Got=%d", 1, numOfObjects) } } + +func TestChangeMonitoringConsoleAnnotations(t *testing.T) { + ctx := context.TODO() + + builder := fake.NewClientBuilder() + client := builder.Build() + utilruntime.Must(enterpriseApi.AddToScheme(clientgoscheme.Scheme)) + + // define CM and MC + cm := &enterpriseApi.ClusterManager{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.ClusterManagerSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + }, + Volumes: []corev1.Volume{}, + }, + }, + } + + mc := &enterpriseApi.MonitoringConsole{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.MonitoringConsoleSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + }, + Volumes: []corev1.Volume{}, + ClusterManagerRef: corev1.ObjectReference{ + Name: "test", + }, + }, + }, + } + cm.Spec.Image = "splunk/splunk:latest" + + // Create the instances + client.Create(ctx, cm) + _, err := ApplyClusterManager(ctx, client, cm) + if err != nil { + t.Errorf("applyClusterManager should not have returned error; err=%v", err) + } + namespacedName := types.NamespacedName{ + Name: cm.Name, + Namespace: cm.Namespace, + } + err = client.Get(ctx, namespacedName, cm) + if err != nil { + t.Errorf("changeMonitoringConsoleAnnotations should not have returned error=%v", err) + } + cm.Status.Phase = enterpriseApi.PhaseReady + err = client.Status().Update(ctx, cm) + if err != nil { + t.Errorf("Unexpected update pod %v", err) + debug.PrintStack() + } + client.Create(ctx, mc) + _, err = ApplyMonitoringConsole(ctx, client, mc) + if err != nil { + t.Errorf("applyMonitoringConsole should not have returned error; err=%v", err) + } + + err = changeMonitoringConsoleAnnotations(ctx, client, cm) + if err != nil { + t.Errorf("changeMonitoringConsoleAnnotations should not have returned error=%v", err) + } + monitoringConsole := &enterpriseApi.MonitoringConsole{} + namespacedName = types.NamespacedName{ + Name: cm.Name, + Namespace: cm.Namespace, + } + err = client.Get(ctx, namespacedName, monitoringConsole) + if err != nil { + t.Errorf("changeMonitoringConsoleAnnotations should not have returned error=%v", err) + } + + annotations := monitoringConsole.GetAnnotations() + if annotations["splunk/image-tag"] != cm.Spec.Image { + t.Errorf("changeMonitoringConsoleAnnotations should have set the checkUpdateImage annotation field to the current image") + } +} diff --git a/pkg/splunk/enterprise/searchheadcluster.go b/pkg/splunk/enterprise/searchheadcluster.go index 8419bb90d..7006ed0c9 100644 --- a/pkg/splunk/enterprise/searchheadcluster.go +++ b/pkg/splunk/enterprise/searchheadcluster.go @@ -49,6 +49,7 @@ func ApplySearchHeadCluster(ctx context.Context, client splcommon.ControllerClie reqLogger := log.FromContext(ctx) scopedLog := reqLogger.WithName("ApplySearchHeadCluster") eventPublisher, _ := newK8EventPublisher(client, cr) + cr.Kind = "SearchHeadCluster" // validate and updates defaults for CR err := validateSearchHeadClusterSpec(ctx, client, cr) @@ -160,6 +161,11 @@ func ApplySearchHeadCluster(ctx context.Context, client splcommon.ControllerClie return result, err } + continueReconcile, err := UpgradePathValidation(ctx, client, cr, cr.Spec.CommonSplunkSpec, nil) + if err != nil || !continueReconcile { + return result, err + } + deployerManager := splctrl.DefaultStatefulSetPodManager{} phase, err := deployerManager.Update(ctx, client, statefulSet, 1) if err != nil { @@ -179,7 +185,7 @@ func ApplySearchHeadCluster(ctx context.Context, client splcommon.ControllerClie return result, err } - mgr := newSerachHeadClusterPodManager(client, scopedLog, cr, namespaceScopedSecret, splclient.NewSplunkClient) + mgr := newSearchHeadClusterPodManager(client, scopedLog, cr, namespaceScopedSecret, splclient.NewSplunkClient) phase, err = mgr.Update(ctx, client, statefulSet, cr.Spec.Replicas) if err != nil { return result, err @@ -247,7 +253,7 @@ type searchHeadClusterPodManager struct { } // newSerachHeadClusterPodManager function to create pod manager this is added to write unit test case -var newSerachHeadClusterPodManager = func(client splcommon.ControllerClient, log logr.Logger, cr *enterpriseApi.SearchHeadCluster, secret *corev1.Secret, newSplunkClient NewSplunkClientFunc) searchHeadClusterPodManager { +var newSearchHeadClusterPodManager = func(client splcommon.ControllerClient, log logr.Logger, cr *enterpriseApi.SearchHeadCluster, secret *corev1.Secret, newSplunkClient NewSplunkClientFunc) searchHeadClusterPodManager { return searchHeadClusterPodManager{ log: log, cr: cr, @@ -553,6 +559,18 @@ func (mgr *searchHeadClusterPodManager) getClient(ctx context.Context, n int32) return mgr.newSplunkClient(fmt.Sprintf("https://%s:8089", fqdnName), "admin", adminPwd) } +// GetSearchHeadClusterMemberInfo used in mocking this function +var GetSearchHeadClusterMemberInfo = func(ctx context.Context, mgr *searchHeadClusterPodManager, n int32) (*splclient.SearchHeadClusterMemberInfo, error) { + c := mgr.getClient(ctx, n) + return c.GetSearchHeadClusterMemberInfo() +} + +// GetSearchHeadCaptainInfo used in mocking this function +var GetSearchHeadCaptainInfo = func(ctx context.Context, mgr *searchHeadClusterPodManager, n int32) (*splclient.SearchHeadCaptainInfo, error) { + c := mgr.getClient(ctx, n) + return c.GetSearchHeadCaptainInfo() +} + // updateStatus for searchHeadClusterPodManager uses the REST API to update the status for a SearcHead custom resource func (mgr *searchHeadClusterPodManager) updateStatus(ctx context.Context, statefulSet *appsv1.StatefulSet) error { // populate members status using REST API to get search head cluster member info @@ -564,10 +582,10 @@ func (mgr *searchHeadClusterPodManager) updateStatus(ctx context.Context, statef } gotCaptainInfo := false for n := int32(0); n < statefulSet.Status.Replicas; n++ { - c := mgr.getClient(ctx, n) + //c := mgr.getClient(ctx, n) memberName := GetSplunkStatefulsetPodName(SplunkSearchHead, mgr.cr.GetName(), n) memberStatus := enterpriseApi.SearchHeadClusterMemberStatus{Name: memberName} - memberInfo, err := c.GetSearchHeadClusterMemberInfo() + memberInfo, err := GetSearchHeadClusterMemberInfo(ctx, mgr, n) if err == nil { memberStatus.Status = memberInfo.Status memberStatus.Adhoc = memberInfo.Adhoc @@ -580,7 +598,7 @@ func (mgr *searchHeadClusterPodManager) updateStatus(ctx context.Context, statef if err == nil && !gotCaptainInfo { // try querying captain api; note that this should work on any node - captainInfo, err := c.GetSearchHeadCaptainInfo() + captainInfo, err := GetSearchHeadCaptainInfo(ctx, mgr, n) if err == nil { mgr.cr.Status.Captain = captainInfo.Label mgr.cr.Status.CaptainReady = captainInfo.ServiceReady diff --git a/pkg/splunk/enterprise/searchheadcluster_test.go b/pkg/splunk/enterprise/searchheadcluster_test.go index 1c6f9fd23..90a1717fb 100644 --- a/pkg/splunk/enterprise/searchheadcluster_test.go +++ b/pkg/splunk/enterprise/searchheadcluster_test.go @@ -68,38 +68,51 @@ func TestApplySearchHeadCluster(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, + {MetaName: "*v1.Service-test-splunk-stack1-search-head-headless"}, {MetaName: "*v1.Service-test-splunk-stack1-search-head-service"}, + {MetaName: "*v1.Service-test-splunk-stack1-deployer-service"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-deployer"}, + {MetaName: "*v1.ConfigMap-test-splunk-test-probe-configmap"}, {MetaName: "*v1.ConfigMap-test-splunk-test-probe-configmap"}, + {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-stack1-deployer-secret-v1"}, + + {MetaName: "*v1.StatefulSet-test-splunk-stack1-search-head"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-deployer"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-search-head"}, + {MetaName: "*v1.ConfigMap-test-splunk-test-probe-configmap"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-stack1-search-head-secret-v1"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-search-head"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-search-head"}, + {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v4.SearchHeadCluster-test-stack1"}, {MetaName: "*v4.SearchHeadCluster-test-stack1"}, } + createFuncCalls := []spltest.MockFuncCall{ {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Service-test-splunk-stack1-search-head-headless"}, {MetaName: "*v1.Service-test-splunk-stack1-search-head-service"}, + {MetaName: "*v1.Service-test-splunk-stack1-deployer-service"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-deployer"}, + {MetaName: "*v1.ConfigMap-test-splunk-test-probe-configmap"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-stack1-deployer-secret-v1"}, + {MetaName: "*v1.StatefulSet-test-splunk-stack1-search-head"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-deployer"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-deployer"}, {MetaName: "*v1.StatefulSet-test-splunk-stack1-search-head"}, + {MetaName: "*v1.ConfigMap-test-splunk-test-probe-configmap"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-stack1-search-head-secret-v1"}, @@ -122,8 +135,8 @@ func TestApplySearchHeadCluster(t *testing.T) { listmockCall := []spltest.MockFuncCall{ {ListOpts: listOpts}} - createCalls := map[string][]spltest.MockFuncCall{"Get": funcCalls, "Create": {funcCalls[0], funcCalls[3], funcCalls[4], funcCalls[5], funcCalls[8], funcCalls[10], funcCalls[11], funcCalls[15], funcCalls[16]}, "Update": {funcCalls[0]}, "List": {listmockCall[0], listmockCall[0]}} - updateCalls := map[string][]spltest.MockFuncCall{"Get": createFuncCalls, "Update": {createFuncCalls[5], createFuncCalls[11]}, "List": {listmockCall[0], listmockCall[0]}} + createCalls := map[string][]spltest.MockFuncCall{"Get": funcCalls, "Create": {funcCalls[0], funcCalls[3], funcCalls[4], funcCalls[5], funcCalls[8], funcCalls[10], funcCalls[12], funcCalls[16], funcCalls[17]}, "Update": {funcCalls[0]}, "List": {listmockCall[0], listmockCall[0]}} + updateCalls := map[string][]spltest.MockFuncCall{"Get": createFuncCalls, "Update": {createFuncCalls[5], createFuncCalls[9]}, "List": {listmockCall[0], listmockCall[0]}} statefulSet := enterpriseApi.SearchHeadCluster{ TypeMeta: metav1.TypeMeta{ Kind: "SearchHeadCluster", @@ -294,7 +307,7 @@ func TestSearchHeadClusterPodManager(t *testing.T) { }, } method = "searchHeadClusterPodManager.Update(All pods ready)" - wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[5]}, "Create": {funcCalls[1]}, "List": {listmockCall[0]}} + wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[2], funcCalls[5]}, "Create": {funcCalls[1]}, "List": {listmockCall[0]}} searchHeadClusterPodManagerTester(t, method, mockHandlers, 1, enterpriseApi.PhaseReady, statefulSet, wantCalls, nil, statefulSet, pod) // test pod needs update => transition to detention @@ -307,7 +320,7 @@ func TestSearchHeadClusterPodManager(t *testing.T) { }) pod.ObjectMeta.Labels["controller-revision-hash"] = "v0" method = "searchHeadClusterPodManager.Update(Quarantine Pod)" - wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[5], funcCalls[2], funcCalls[2]}, "Create": {funcCalls[1]}} + wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[2], funcCalls[5], funcCalls[2], funcCalls[2]}, "Create": {funcCalls[1]}} searchHeadClusterPodManagerTester(t, method, mockHandlers, 1, enterpriseApi.PhaseUpdating, statefulSet, wantCalls, nil, statefulSet, pod) // test pod needs update => wait for searches to drain @@ -315,13 +328,13 @@ func TestSearchHeadClusterPodManager(t *testing.T) { mockHandlers[0].Body = strings.Replace(mockHandlers[0].Body, `"status":"Up"`, `"status":"ManualDetention"`, 1) mockHandlers[0].Body = strings.Replace(mockHandlers[0].Body, `"active_historical_search_count":0`, `"active_historical_search_count":1`, 1) method = "searchHeadClusterPodManager.Update(Draining Searches)" - wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[5]}, "Create": {funcCalls[1]}} + wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[2], funcCalls[5]}, "Create": {funcCalls[1]}} searchHeadClusterPodManagerTester(t, method, mockHandlers, 1, enterpriseApi.PhaseUpdating, statefulSet, wantCalls, nil, statefulSet, pod) // test pod needs update => delete pod mockHandlers[0].Body = strings.Replace(mockHandlers[0].Body, `"active_historical_search_count":1`, `"active_historical_search_count":0`, 1) method = "searchHeadClusterPodManager.Update(Delete Pod)" - wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[5]}, "Create": {funcCalls[1]}, "Delete": {funcCalls[5]}} + wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[2], funcCalls[5]}, "Create": {funcCalls[1]}, "Delete": {funcCalls[5]}} searchHeadClusterPodManagerTester(t, method, mockHandlers, 1, enterpriseApi.PhaseUpdating, statefulSet, wantCalls, nil, statefulSet, pod) // test pod update finished => release from detention @@ -334,7 +347,7 @@ func TestSearchHeadClusterPodManager(t *testing.T) { Body: ``, }) method = "searchHeadClusterPodManager.Update(Release Quarantine)" - wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[5], funcCalls[2]}, "Create": {funcCalls[1]}} + wantCalls = map[string][]spltest.MockFuncCall{"Get": {funcCalls[0], funcCalls[1], funcCalls[1], funcCalls[2], funcCalls[2], funcCalls[5], funcCalls[2]}, "Create": {funcCalls[1]}} searchHeadClusterPodManagerTester(t, method, mockHandlers, 1, enterpriseApi.PhaseUpdating, statefulSet, wantCalls, nil, statefulSet, pod) // test scale down => remove member @@ -362,6 +375,7 @@ func TestSearchHeadClusterPodManager(t *testing.T) { {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Secret-test-splunk-test-secret"}, {MetaName: "*v1.Pod-test-splunk-stack1-search-head-0"}, + {MetaName: "*v1.Pod-test-splunk-stack1-search-head-0"}, {MetaName: "*v1.Pod-test-splunk-stack1-search-head-1"}, {MetaName: "*v1.Pod-test-splunk-stack1-search-head-1"}, {MetaName: "*v1.PersistentVolumeClaim-test-pvc-etc-splunk-stack1-1"}, @@ -652,25 +666,25 @@ func TestGetSearchHeadStatefulSet(t *testing.T) { } cr.Spec.Replicas = 3 - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":3,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"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_search_head"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":3,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"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_search_head"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.Replicas = 4 - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":4,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"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_search_head"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":4,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"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_search_head"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.Replicas = 5 cr.Spec.ClusterManagerRef.Name = "stack1" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":5,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service"},{"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_search_head"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":5,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service"},{"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_search_head"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.Replicas = 6 cr.Spec.ClusterManagerRef.Namespace = "test2" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.DefaultsURLApps = "/mnt/apps/apps.yml" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Define additional service port in CR and verified the statefulset has the new port - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Create a serviceaccount current := corev1.ServiceAccount{ @@ -681,7 +695,7 @@ func TestGetSearchHeadStatefulSet(t *testing.T) { } _ = splutil.CreateResource(ctx, c, ¤t) cr.Spec.ServiceAccount = "defaults" - test(` {"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Add extraEnv cr.Spec.CommonSplunkSpec.ExtraEnv = []corev1.EnvVar{ @@ -690,7 +704,7 @@ func TestGetSearchHeadStatefulSet(t *testing.T) { Value: "test_value", }, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-search-head","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":6,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-3.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-4.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-5.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_DEPLOYER_URL","value":"splunk-stack1-deployer-service"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack1-cluster-manager-service.test2.svc.cluster.local"},{"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_search_head"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-search-head"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-search-head","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"search-head","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-search-head-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) } func TestGetDeployerStatefulSet(t *testing.T) { @@ -719,11 +733,11 @@ func TestGetDeployerStatefulSet(t *testing.T) { } cr.Spec.Replicas = 3 - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-deployer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-deployer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"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_deployer"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-deployer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-deployer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-deployer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-deployer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"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_deployer"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-deployer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-deployer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Allow installation of apps via DefaultsURLApps on the SHCDeployer cr.Spec.DefaultsURLApps = "/mnt/apps/apps.yml" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-deployer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-deployer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_deployer"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-deployer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-deployer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-deployer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-deployer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_deployer"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-deployer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-deployer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Create a serviceaccount current := corev1.ServiceAccount{ @@ -735,7 +749,7 @@ func TestGetDeployerStatefulSet(t *testing.T) { _ = splutil.CreateResource(ctx, c, ¤t) cr.Spec.ServiceAccount = "defaults" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-deployer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-deployer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_deployer"},{"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"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-deployer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-deployer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-deployer","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-deployer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"http-splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"https-splunkd","containerPort":8089,"protocol":"TCP"}],"env":[{"name":"SPLUNK_SEARCH_HEAD_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-1.splunk-stack1-search-head-headless.test.svc.cluster.local,splunk-stack1-search-head-2.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_SEARCH_HEAD_CAPTAIN_URL","value":"splunk-stack1-search-head-0.splunk-stack1-search-head-headless.test.svc.cluster.local"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_deployer"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-deployer"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"search-head","app.kubernetes.io/instance":"splunk-stack1-deployer","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"deployer","app.kubernetes.io/part-of":"splunk-stack1-search-head"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-deployer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) } func TestAppFrameworkSearchHeadClusterShouldNotFail(t *testing.T) { @@ -1436,7 +1450,7 @@ func TestSearchHeadClusterWithReadyState(t *testing.T) { } // mock new search pod manager - newSerachHeadClusterPodManager = func(client splcommon.ControllerClient, log logr.Logger, cr *enterpriseApi.SearchHeadCluster, secret *corev1.Secret, newSplunkClient NewSplunkClientFunc) searchHeadClusterPodManager { + newSearchHeadClusterPodManager = func(client splcommon.ControllerClient, log logr.Logger, cr *enterpriseApi.SearchHeadCluster, secret *corev1.Secret, newSplunkClient NewSplunkClientFunc) searchHeadClusterPodManager { return searchHeadClusterPodManager{ log: log, cr: cr, @@ -1542,7 +1556,11 @@ func TestSearchHeadClusterWithReadyState(t *testing.T) { Name: searchheadcluster.Name, Namespace: searchheadcluster.Namespace, } - + err = c.Get(ctx, namespacedName, searchheadcluster) + if err != nil { + t.Errorf("Unexpected get search head cluster. Error=%v", err) + debug.PrintStack() + } // simulate Ready state searchheadcluster.Status.Phase = enterpriseApi.PhaseReady searchheadcluster.Spec.ServiceTemplate.Annotations = map[string]string{ @@ -1869,7 +1887,6 @@ func TestSearchHeadClusterWithReadyState(t *testing.T) { // call reconciliation _, err = ApplySearchHeadCluster(ctx, c, searchheadcluster) if err != nil { - t.Errorf("Unexpected error while running reconciliation for search head cluster with app framework %v", err) - debug.PrintStack() + t.Errorf("Unexpected error while running reconciliation for search head cluster with app framework. Error=%v", err) } } diff --git a/pkg/splunk/enterprise/standalone.go b/pkg/splunk/enterprise/standalone.go index b8ec3d976..5eed285aa 100644 --- a/pkg/splunk/enterprise/standalone.go +++ b/pkg/splunk/enterprise/standalone.go @@ -49,6 +49,7 @@ func ApplyStandalone(ctx context.Context, client splcommon.ControllerClient, cr cr.Status.ResourceRevMap = make(map[string]string) } eventPublisher, _ := newK8EventPublisher(client, cr) + cr.Kind = "Standalone" // validate and updates defaults for CR err := validateStandaloneSpec(ctx, client, cr) diff --git a/pkg/splunk/enterprise/standalone_test.go b/pkg/splunk/enterprise/standalone_test.go index be8903b9f..45ddd9398 100644 --- a/pkg/splunk/enterprise/standalone_test.go +++ b/pkg/splunk/enterprise/standalone_test.go @@ -342,11 +342,11 @@ func TestGetStandaloneStatefulSet(t *testing.T) { } configTester(t, "getStandaloneStatefulSet()", f, want) } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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-stack1-standalone-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"}],"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_standalone"},{"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"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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-stack1-standalone-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"}],"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_standalone"},{"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"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.EtcVolumeStorageConfig.EphemeralStorage = true cr.Spec.VarVolumeStorageConfig.EphemeralStorage = true - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"mnt-splunk-etc","emptyDir":{}},{"name":"mnt-splunk-var","emptyDir":{}},{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-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"}],"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_standalone"},{"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"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"mnt-splunk-etc","mountPath":"/opt/splunk/etc"},{"name":"mnt-splunk-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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"mnt-splunk-etc","emptyDir":{}},{"name":"mnt-splunk-var","emptyDir":{}},{"name":"splunk-test-probe-configmap","configMap":{"name":"splunk-test-probe-configmap","defaultMode":365}},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-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"}],"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_standalone"},{"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"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"mnt-splunk-etc","mountPath":"/opt/splunk/etc"},{"name":"mnt-splunk-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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"default-scheduler"}},"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.EtcVolumeStorageConfig.EphemeralStorage = false cr.Spec.VarVolumeStorageConfig.EphemeralStorage = false @@ -360,10 +360,10 @@ func TestGetStandaloneStatefulSet(t *testing.T) { cr.Spec.Volumes = []corev1.Volume{ {Name: "defaults"}, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-standalone-defaults","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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-standalone-defaults","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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) cr.Spec.DefaultsURLApps = "/mnt/apps/apps.yml" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-standalone-defaults","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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-standalone-defaults","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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Create a serviceaccount current := corev1.ServiceAccount{ @@ -374,7 +374,7 @@ func TestGetStandaloneStatefulSet(t *testing.T) { } _ = splutil.CreateResource(ctx, c, ¤t) cr.Spec.ServiceAccount = "defaults" - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-standalone-defaults","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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-standalone-defaults","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"}],"env":[{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) // Add extraEnv cr.Spec.CommonSplunkSpec.ExtraEnv = []corev1.EnvVar{ @@ -383,7 +383,7 @@ func TestGetStandaloneStatefulSet(t *testing.T) { Value: "test_value", }, } - test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-standalone-defaults","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"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"runAsNonRoot":true,"fsGroup":41812},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) + test(`{"kind":"StatefulSet","apiVersion":"apps/v1","metadata":{"name":"splunk-stack1-standalone","namespace":"test","creationTimestamp":null,"ownerReferences":[{"apiVersion":"","kind":"","name":"stack1","uid":"","controller":true}]},"spec":{"replicas":1,"selector":{"matchLabels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"},"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":"defaults"},{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-standalone-secret-v1","defaultMode":420}},{"name":"mnt-splunk-defaults","configMap":{"name":"splunk-stack1-standalone-defaults","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"}],"env":[{"name":"TEST_ENV_VAR","value":"test_value"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-manager-service"},{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-defaults/default.yml,/mnt/defaults/defaults.yml,/mnt/apps/apps.yml,/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"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"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"}],"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},"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":100,"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/instance","operator":"In","values":["splunk-stack1-standalone"]}]},"topologyKey":"kubernetes.io/hostname"}}]}},"schedulerName":"custom-scheduler"}},"volumeClaimTemplates":[{"metadata":{"name":"pvc-etc","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}},"storageClassName":"gp2"},"status":{}},{"metadata":{"name":"pvc-var","namespace":"test","creationTimestamp":null,"labels":{"app.kubernetes.io/component":"standalone","app.kubernetes.io/instance":"splunk-stack1-standalone","app.kubernetes.io/managed-by":"splunk-operator","app.kubernetes.io/name":"standalone","app.kubernetes.io/part-of":"splunk-stack1-standalone"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}},"storageClassName":"gp2"},"status":{}}],"serviceName":"splunk-stack1-standalone-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0,"availableReplicas":0}}`) } @@ -1281,7 +1281,11 @@ func TestStandaloneWithReadyState(t *testing.T) { Name: standalone.Name, Namespace: standalone.Namespace, } - + err = c.Get(ctx, namespacedName, &standalone) + if err != nil { + t.Errorf("Unexpected get standalone. Error=%v", err) + debug.PrintStack() + } // simulate Ready state standalone.Status.Phase = enterpriseApi.PhaseReady standalone.Spec.ServiceTemplate.Annotations = map[string]string{ diff --git a/pkg/splunk/enterprise/upgrade.go b/pkg/splunk/enterprise/upgrade.go new file mode 100644 index 000000000..68759f2ad --- /dev/null +++ b/pkg/splunk/enterprise/upgrade.go @@ -0,0 +1,315 @@ +package enterprise + +import ( + "context" + "fmt" + + 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" + appsv1 "k8s.io/api/apps/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + rclient "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" +) + +// helps in mock function +var GetClusterInfoCall = func(ctx context.Context, mgr *indexerClusterPodManager, mockCall bool) (*splclient.ClusterInfo, error) { + cm := mgr.getClusterManagerClient(ctx) + return cm.GetClusterInfo(false) +} + +// UpgradePathValidation is used in validating if upgrade can be done to given custom resource +// +// the method follows the sequence +// 1. Standalone or License Manager +// 2. Cluster Manager - if LM ref is defined, wait for License manager to complete +// 3. Monitoring Console - if CM ref is defined, wait for Cluster Manager to complete +// 4. Search Head Cluster - if MC ref , CM ref , LM ref is defined, wait for them to complete in order, +// if any one of them not defined, ignore them and wait for the one added in ref +// 5. Indexer Cluster - same as above also wait for search head cluster to complete before starting upgrade +// if its multisite then do 1 site at a time +// function returns bool and error , true - go ahead with upgrade +// false - exit the reconciliation loop with error +func UpgradePathValidation(ctx context.Context, c splcommon.ControllerClient, cr splcommon.MetaObject, spec enterpriseApi.CommonSplunkSpec, mgr *indexerClusterPodManager) (bool, error) { + reqLogger := log.FromContext(ctx) + scopedLog := reqLogger.WithName("isClusterManagerReadyForUpgrade").WithValues("name", cr.GetName(), "namespace", cr.GetNamespace()) + eventPublisher, _ := newK8EventPublisher(c, cr) + kind := cr.GroupVersionKind().Kind + scopedLog.Info("kind is set to ", "kind", kind) + // start from standalone first + goto Standalone + + // if custom resource type is standalone or license manager go ahead and upgrade +Standalone: + if cr.GroupVersionKind().Kind == "Standalone" { + return true, nil + } else { + goto LicenseManager + } +LicenseManager: + if cr.GroupVersionKind().Kind == "LicenseManager" { + return true, nil + } else { + licenseManagerRef := spec.LicenseManagerRef + // if custom resource type not license manager or standalone then + // check if there is license manager reference + // if no reference go to cluster manager + if licenseManagerRef.Name == "" { + goto ClusterManager + } + + namespacedName := types.NamespacedName{Namespace: cr.GetNamespace(), Name: licenseManagerRef.Name} + licenseManager := &enterpriseApi.LicenseManager{} + // get the license manager referred in CR + err := c.Get(ctx, namespacedName, licenseManager) + if err != nil { + if k8serrors.IsNotFound(err) { + goto ClusterManager + } + return false, err + } + + // get current image of license manager + lmImage, err := getCurrentImage(ctx, c, licenseManager, SplunkLicenseManager) + if err != nil { + eventPublisher.Warning(ctx, "isClusterManagerReadyForUpgrade", fmt.Sprintf("Could not get the License Manager Image. Reason %v", err)) + scopedLog.Error(err, "Unable to get licenseManager current image") + return false, err + } + // if license manager status is ready and CR spec and current license manager image are not same + // then return with error + if licenseManager.Status.Phase != enterpriseApi.PhaseReady || lmImage != spec.Image { + return false, fmt.Errorf("license manager is not ready or license manager current image is different than CR image") + } + goto ClusterManager + } +ClusterManager: + if cr.GroupVersionKind().Kind == "ClusterManager" { + + licenseManagerRef := spec.LicenseManagerRef + if licenseManagerRef.Name == "" { + return true, nil + } + namespacedName := types.NamespacedName{ + Namespace: cr.GetNamespace(), + Name: GetSplunkStatefulsetName(SplunkClusterManager, cr.GetName()), + } + + // check if the stateful set is created at this instance + statefulSet := &appsv1.StatefulSet{} + err := c.Get(ctx, namespacedName, statefulSet) + if err != nil { + if k8serrors.IsNotFound(err) { + return true, nil + } + return false, nil + } + return true, nil + } else { + // check if a cluster manager reference is added to custom resource + clusterManagerRef := spec.ClusterManagerRef + if clusterManagerRef.Name == "" { + // if ref is not defined go to monitoring console step + goto MonitoringConsole + } + + namespacedName := types.NamespacedName{Namespace: cr.GetNamespace(), Name: clusterManagerRef.Name} + clusterManager := &enterpriseApi.ClusterManager{} + + // get the cluster manager referred in custom resource + err := c.Get(ctx, namespacedName, clusterManager) + if err != nil { + eventPublisher.Warning(ctx, "UpgradePathValidation", fmt.Sprintf("Could not find the Cluster Manager. Reason %v", err)) + scopedLog.Error(err, "Unable to get clusterManager") + goto MonitoringConsole + } + + /// get the cluster manager image referred in custom resource + cmImage, err := getCurrentImage(ctx, c, clusterManager, SplunkClusterManager) + if err != nil { + eventPublisher.Warning(ctx, "UpgradePathValidation", fmt.Sprintf("Could not get the Cluster Manager Image. Reason %v", err)) + scopedLog.Error(err, "Unable to get clusterManager current image") + return false, err + } + + // check if an image upgrade is happening and whether CM has finished updating yet, return false to stop + // further reconcile operations on custom resource until CM is ready + if clusterManager.Status.Phase != enterpriseApi.PhaseReady || cmImage != spec.Image { + return false, nil + } + goto MonitoringConsole + } +MonitoringConsole: + if cr.GroupVersionKind().Kind == "MonitoringConsole" { + + namespacedName := types.NamespacedName{ + Namespace: cr.GetNamespace(), + Name: GetSplunkStatefulsetName(SplunkMonitoringConsole, cr.GetName()), + } + + // check if the stateful set is created at this instance + statefulSet := &appsv1.StatefulSet{} + err := c.Get(ctx, namespacedName, statefulSet) + if err != nil { + if k8serrors.IsNotFound(err) { + return true, nil + } + return false, nil + } + return true, nil + } else { + + // check if a MonitoringConsole is attached to the instance + monitoringConsoleRef := spec.MonitoringConsoleRef + if monitoringConsoleRef.Name == "" { + goto SearchHeadCluster + } + + namespacedName := types.NamespacedName{Namespace: cr.GetNamespace(), Name: monitoringConsoleRef.Name} + monitoringConsole := &enterpriseApi.MonitoringConsole{} + + // get the monitoring console referred in custom resource + err := c.Get(ctx, namespacedName, monitoringConsole) + if err != nil { + if k8serrors.IsNotFound(err) { + goto SearchHeadCluster + } + eventPublisher.Warning(ctx, "UpgradePathValidation", fmt.Sprintf("Could not find the Monitoring Console. Reason %v", err)) + scopedLog.Error(err, "Unable to get Monitoring Console") + return false, err + } + + mcImage, err := getCurrentImage(ctx, c, monitoringConsole, SplunkMonitoringConsole) + if err != nil { + eventPublisher.Warning(ctx, "UpgradePathValidation", fmt.Sprintf("Could not get the Monitoring Console Image. Reason %v", err)) + scopedLog.Error(err, "Unable to get Monitoring Console current image") + return false, err + } + + // check if an image upgrade is happening and whether MC has finished updating yet, return false to stop + // further reconcile operations on custom resource until MC is ready + if monitoringConsole.Status.Phase != enterpriseApi.PhaseReady || mcImage != spec.Image { + return false, nil + } + + goto SearchHeadCluster + } +SearchHeadCluster: + if cr.GroupVersionKind().Kind == "SearchHeadCluster" { + + namespacedName := types.NamespacedName{ + Namespace: cr.GetNamespace(), + Name: GetSplunkStatefulsetName(SplunkSearchHead, cr.GetName()), + } + + // check if the stateful set is created at this instance + statefulSet := &appsv1.StatefulSet{} + err := c.Get(ctx, namespacedName, statefulSet) + if err != nil { + if k8serrors.IsNotFound(err) { + return true, nil + } + return false, nil + } + return true, nil + } else { + + // get the clusterManagerRef attached to the instance + clusterManagerRef := spec.ClusterManagerRef + + // check if a search head cluster exists with the same ClusterManager instance attached + searchHeadClusterInstance := enterpriseApi.SearchHeadCluster{} + opts := []rclient.ListOption{ + rclient.InNamespace(cr.GetNamespace()), + } + searchHeadList, err := getSearchHeadClusterList(ctx, c, cr, opts) + if err != nil { + if err.Error() == "NotFound" { + goto IndexerCluster + } + return false, err + } + if len(searchHeadList.Items) == 0 { + goto IndexerCluster + } + + // check if instance has the ClusterManagerRef defined + for _, shc := range searchHeadList.Items { + if shc.Spec.ClusterManagerRef.Name == clusterManagerRef.Name { + searchHeadClusterInstance = shc + break + } + } + if len(searchHeadClusterInstance.GetName()) == 0 { + goto IndexerCluster + } + + shcImage, err := getCurrentImage(ctx, c, &searchHeadClusterInstance, SplunkSearchHead) + if err != nil { + eventPublisher.Warning(ctx, "UpgradePathValidation", fmt.Sprintf("Could not get the Search Head Cluster Image. Reason %v", err)) + scopedLog.Error(err, "Unable to get SearchHeadCluster current image") + return false, err + } + + // check if an image upgrade is happening and whether SHC has finished updating yet, return false to stop + // further reconcile operations on IDX until SHC is ready + if searchHeadClusterInstance.Status.Phase != enterpriseApi.PhaseReady || shcImage != spec.Image { + return false, nil + } + goto IndexerCluster + } +IndexerCluster: + if cr.GroupVersionKind().Kind == "IndexerCluster" { + + // if manager client is not defined, then assign current client + if mgr.c == nil { + mgr.c = c + } + + // check cluster info call using splunk rest api + clusterInfo, err := GetClusterInfoCall(ctx, mgr, false) + if err != nil { + return false, fmt.Errorf("could not get cluster info from cluster manager") + } + // check if cluster is multisite + if clusterInfo.MultiSite == "true" { + opts := []rclient.ListOption{ + rclient.InNamespace(cr.GetNamespace()), + } + indexerList, err := getIndexerClusterList(ctx, c, cr, opts) + if err != nil { + return false, err + } + // get sorted current indexer site list + sortedList, err := getIndexerClusterSortedSiteList(ctx, c, spec.ClusterManagerRef, indexerList) + + preIdx := enterpriseApi.IndexerCluster{} + + for i, v := range sortedList.Items { + if &v == cr { + if i > 0 { + preIdx = sortedList.Items[i-1] + } + break + + } + } + if len(preIdx.Name) != 0 { + // check if previous indexer have completed before starting next one + image, _ := getCurrentImage(ctx, c, &preIdx, SplunkIndexer) + if preIdx.Status.Phase != enterpriseApi.PhaseReady || image != spec.Image { + return false, nil + } + } + + } + return true, nil + } else { + goto EndLabel + } +EndLabel: + return true, nil + +} diff --git a/pkg/splunk/enterprise/upgrade_test.go b/pkg/splunk/enterprise/upgrade_test.go new file mode 100644 index 000000000..f965e1782 --- /dev/null +++ b/pkg/splunk/enterprise/upgrade_test.go @@ -0,0 +1,726 @@ +package enterprise + +import ( + "context" + "fmt" + "runtime/debug" + "testing" + + enterpriseApi "github.com/splunk/splunk-operator/api/v4" + splclient "github.com/splunk/splunk-operator/pkg/splunk/client" + "github.com/splunk/splunk-operator/pkg/splunk/common" + splcommon "github.com/splunk/splunk-operator/pkg/splunk/common" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func TestUpgradePathValidation(t *testing.T) { + + builder := fake.NewClientBuilder() + client := builder.Build() + utilruntime.Must(enterpriseApi.AddToScheme(clientgoscheme.Scheme)) + + ctx := context.TODO() + stdln := enterpriseApi.Standalone{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.StandaloneSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + Image: "splunk/splunk:old", + }, + Volumes: []corev1.Volume{}, + }, + }, + } + + err := client.Create(ctx, &stdln) + if err != nil { + t.Errorf("create should not have returned error; err=%v", err) + } + _, err = ApplyStandalone(ctx, client, &stdln) + if err != nil { + t.Errorf("ApplyStandalone should not have returned error; err=%v", err) + } + + // cluster manager + + lm := enterpriseApi.LicenseManager{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.LicenseManagerSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + Image: "splunk/splunk:old", + }, + Volumes: []corev1.Volume{}, + }, + }, + } + + cm := enterpriseApi.ClusterManager{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.ClusterManagerSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + Image: "splunk/splunk:old", + }, + Volumes: []corev1.Volume{}, + LicenseManagerRef: corev1.ObjectReference{ + Name: "test", + }, + }, + }, + } + + mc := enterpriseApi.MonitoringConsole{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.MonitoringConsoleSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + Image: "splunk/splunk:old", + }, + Volumes: []corev1.Volume{}, + LicenseManagerRef: corev1.ObjectReference{ + Name: "test", + }, + ClusterManagerRef: corev1.ObjectReference{ + Name: "test", + }, + }, + }, + } + + idx := enterpriseApi.IndexerCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.IndexerClusterSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + Image: "splunk/splunk:old", + }, + Volumes: []corev1.Volume{}, + LicenseManagerRef: corev1.ObjectReference{ + Name: "test", + }, + ClusterManagerRef: corev1.ObjectReference{ + Name: "test", + }, + MonitoringConsoleRef: corev1.ObjectReference{ + Name: "test", + }, + }, + }, + } + + shc := enterpriseApi.SearchHeadCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.SearchHeadClusterSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + Image: "splunk/splunk:old", + }, + Volumes: []corev1.Volume{}, + LicenseManagerRef: corev1.ObjectReference{ + Name: "test", + }, + ClusterManagerRef: corev1.ObjectReference{ + Name: "test", + }, + MonitoringConsoleRef: corev1.ObjectReference{ + Name: "test", + }, + }, + }, + } + + err = client.Create(ctx, &lm) + if err != nil { + t.Errorf("create should not have returned error; err=%v", err) + } + err = client.Create(ctx, &cm) + if err != nil { + t.Errorf("create should not have returned error; err=%v", err) + } + err = client.Create(ctx, &mc) + if err != nil { + t.Errorf("create should not have returned error; err=%v", err) + } + err = client.Create(ctx, &idx) + if err != nil { + t.Errorf("create should not have returned error; err=%v", err) + } + err = client.Create(ctx, &shc) + if err != nil { + t.Errorf("create should not have returned error; err=%v", err) + } + + _, err = ApplySearchHeadCluster(ctx, client, &shc) + // license manager statefulset is not created so if its NotFound error we are good + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("ApplySearchHeadCluster should not have returned error; err=%v", err) + } + + _, err = ApplyIndexerClusterManager(ctx, client, &idx) + // license manager statefulset is not created so if its NotFound error we are good + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("ApplyIndexerClusterManagershould not have returned error; err=%v", err) + } + + _, err = ApplyMonitoringConsole(ctx, client, &mc) + // license manager statefulset is not created so if its NotFound error we are good + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("applyMonitoringConsole should not have returned error; err=%v", err) + } + + _, err = ApplyClusterManager(ctx, client, &cm) + // license manager statefulset is not created + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("applyClusterManager should not have returned error; err=%v", err) + } + + // create license manager statefulset + _, err = ApplyLicenseManager(ctx, client, &lm) + if err != nil { + t.Errorf("ApplyLicenseManager should not have returned error; err=%v", err) + } + + // create pods for license manager + createPods(t, ctx, client, "license-manager", fmt.Sprintf("splunk-%s-license-manager-0", lm.Name), lm.Namespace, lm.Spec.Image) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-license-manager", lm.Name), lm.Namespace) + lm.Status.TelAppInstalled = true + // create license manager statefulset + _, err = ApplyLicenseManager(ctx, client, &lm) + if err != nil { + t.Errorf("ApplyLicenseManager should not have returned error; err=%v", err) + } + + shc.Status.TelAppInstalled = true + _, err = ApplySearchHeadCluster(ctx, client, &shc) + // cluster manager statefulset is not created so if its NotFound error we are good + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("ApplySearchHeadCluster should not have returned error; err=%v", err) + } + + _, err = ApplyIndexerClusterManager(ctx, client, &idx) + // cluster manager statefulset is not created so if its NotFound error we are good + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("ApplyIndexerClusterManagershould not have returned error; err=%v", err) + } + + _, err = ApplyMonitoringConsole(ctx, client, &mc) + // cluster manager statefulset is not created so if its NotFound error we are good + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("applyMonitoringConsole should not have returned error; err=%v", err) + } + + namespacedName := types.NamespacedName{ + Name: "test", + Namespace: "test", + } + err = client.Get(ctx, namespacedName, &lm) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + + if lm.Status.Phase != enterpriseApi.PhaseReady { + t.Errorf("lm is not in ready state") + } + + _, err = ApplyClusterManager(ctx, client, &cm) + // lm statefulset should have been created by now, this should pass + if err != nil { + t.Errorf("applyClusterManager should not have returned error; err=%v", err) + } + + // create pods for cluster manager + createPods(t, ctx, client, "cluster-manager", fmt.Sprintf("splunk-%s-cluster-manager-0", cm.Name), cm.Namespace, cm.Spec.Image) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-cluster-manager", cm.Name), cm.Namespace) + cm.Status.TelAppInstalled = true + // cluster manager is found and creat + _, err = ApplyClusterManager(ctx, client, &cm) + // lm statefulset should have been created by now, this should pass + if err != nil { + t.Errorf("applyClusterManager should not have returned error; err=%v", err) + } + + err = client.Get(ctx, namespacedName, &cm) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + + if cm.Status.Phase != enterpriseApi.PhaseReady { + t.Errorf("cm is not in ready state") + } + + shc.Status.TelAppInstalled = true + _, err = ApplySearchHeadCluster(ctx, client, &shc) + // monitoring console statefulset is not created so if its NotFound error we are good + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("ApplySearchHeadCluster should not have returned error; err=%v", err) + } + + // mock the verify RF peer funciton + VerifyRFPeers = func(ctx context.Context, mgr indexerClusterPodManager, client splcommon.ControllerClient) error { + return nil + } + + _, err = ApplyIndexerClusterManager(ctx, client, &idx) + // monitoring console statefulset is not created so if its NotFound error we are good + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("ApplyIndexerClusterManager should not have returned error; err=%v", err) + } + + // mointoring console statefulset is created here + _, err = ApplyMonitoringConsole(ctx, client, &mc) + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("applyMonitoringConsole should not have returned error; err=%v", err) + } + // create pods for cluster manager + createPods(t, ctx, client, "monitoring-console", fmt.Sprintf("splunk-%s-monitoring-console-0", lm.Name), lm.Namespace, lm.Spec.Image) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-monitoring-console", lm.Name), lm.Namespace) + // mointoring console statefulset is created here + _, err = ApplyMonitoringConsole(ctx, client, &mc) + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("applyMonitoringConsole should not have returned error; err=%v", err) + } + + err = client.Get(ctx, namespacedName, &mc) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + + if mc.Status.Phase != enterpriseApi.PhaseReady { + t.Errorf("mc is not in ready state") + } + + // Monitoring console is ready now, now this should crete statefulset but statefulset is not in ready phase + shc.Status.TelAppInstalled = true + _, err = ApplySearchHeadCluster(ctx, client, &shc) + if err != nil { + t.Errorf("ApplySearchHeadCluster should not have returned error; err=%v", err) + } + + // create pods for cluster manager + createPods(t, ctx, client, "search-head", fmt.Sprintf("splunk-%s-search-head-0", shc.Name), shc.Namespace, shc.Spec.Image) + createPods(t, ctx, client, "search-head", fmt.Sprintf("splunk-%s-search-head-1", shc.Name), shc.Namespace, shc.Spec.Image) + createPods(t, ctx, client, "search-head", fmt.Sprintf("splunk-%s-search-head-2", shc.Name), shc.Namespace, shc.Spec.Image) + updateStatefulSetsInTest(t, ctx, client, 3, fmt.Sprintf("splunk-%s-search-head", shc.Name), shc.Namespace) + createPods(t, ctx, client, "deployer", fmt.Sprintf("splunk-%s-deployer-0", shc.Name), shc.Namespace, shc.Spec.Image) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-deployer", shc.Name), shc.Namespace) + + // used in mocking this function + GetSearchHeadClusterMemberInfo = func(ctx context.Context, mgr *searchHeadClusterPodManager, n int32) (*splclient.SearchHeadClusterMemberInfo, error) { + shcm := &splclient.SearchHeadClusterMemberInfo{ + Status: "Up", + } + return shcm, nil + } + + // used in mocking this function + GetSearchHeadCaptainInfo = func(ctx context.Context, mgr *searchHeadClusterPodManager, n int32) (*splclient.SearchHeadCaptainInfo, error) { + shci := &splclient.SearchHeadCaptainInfo{ + ServiceReady: true, + Initialized: true, + } + return shci, nil + } + // Now SearchheadCluster should move to READY state + shc.Status.TelAppInstalled = true + _, err = ApplySearchHeadCluster(ctx, client, &shc) + if err != nil { + t.Errorf("ApplySearchHeadCluster should not have returned error; err=%v", err) + } + + err = client.Get(ctx, namespacedName, &shc) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + + if shc.Status.Phase != enterpriseApi.PhaseReady { + t.Errorf("shc is not in ready state") + } + + // mock the verify RF peer funciton + VerifyRFPeers = func(ctx context.Context, mgr indexerClusterPodManager, client splcommon.ControllerClient) error { + return nil + } + + // mock the call + GetClusterInfoCall = func(ctx context.Context, mgr *indexerClusterPodManager, mockCall bool) (*splclient.ClusterInfo, error) { + cinfo := &splclient.ClusterInfo{ + MultiSite: "false", + } + return cinfo, nil + } + GetClusterManagerPeersCall = func(ctx context.Context, mgr *indexerClusterPodManager) (map[string]splclient.ClusterManagerPeerInfo, error) { + response := map[string]splclient.ClusterManagerPeerInfo{ + "splunk-test-indexer-0": { + ID: "site-1", + Status: "Up", + ActiveBundleID: "1", + BucketCount: 10, + Searchable: true, + }, + } + return response, err + } + GetClusterManagerInfoCall = func(ctx context.Context, mgr *indexerClusterPodManager) (*splclient.ClusterManagerInfo, error) { + response := &splclient.ClusterManagerInfo{ + Initialized: true, + IndexingReady: true, + ServiceReady: true, + } + return response, err + } + + // search head cluster is ready, this should create statefulset but they are not ready + _, err = ApplyIndexerClusterManager(ctx, client, &idx) + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("ApplyIndexerClusterManager should not have returned error; err=%v", err) + } + + // create pods for indexer cluster + createPods(t, ctx, client, "indexer", fmt.Sprintf("splunk-%s-indexer-0", idx.Name), idx.Namespace, idx.Spec.Image) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-indexer", idx.Name), idx.Namespace) + + // search head cluster is not ready, so wait for search head cluster + _, err = ApplyIndexerClusterManager(ctx, client, &idx) + if err != nil && !k8serrors.IsNotFound(err) { + t.Errorf("ApplyIndexerClusterManager should not have returned error; err=%v", err) + } + + err = client.Get(ctx, namespacedName, &idx) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + + if idx.Status.Phase != enterpriseApi.PhaseReady { + t.Errorf("shc is not in ready state") + } + + VerifyCMisMultisiteCall = func(ctx context.Context, cr *enterpriseApi.ClusterManager, namespaceScopedSecret *corev1.Secret) ([]corev1.EnvVar, error) { + extraEnv := getClusterManagerExtraEnv(cr, &cr.Spec.CommonSplunkSpec) + return extraEnv, err + } + + // ------- Step2 starts here ----- + // Update + // standalone + err = client.Get(ctx, namespacedName, &stdln) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + + stdln.Spec.Image = "splunk/splunk:latest" + err = client.Update(ctx, &stdln) + if err != nil { + t.Errorf("update should not have returned error; err=%v", err) + } + _, err = ApplyStandalone(ctx, client, &stdln) + if err != nil { + t.Errorf("ApplyStandalone should not have returned error; err=%v", err) + } + + // cluster manager + err = client.Get(ctx, namespacedName, &cm) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + + cm.Spec.Image = "splunk/splunk:latest" + err = client.Update(ctx, &cm) + if err != nil { + t.Errorf("update should not have returned error; err=%v", err) + } + + // license manager + err = client.Get(ctx, namespacedName, &lm) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + lm.Spec.Image = "splunk/splunk:latest" + err = client.Update(ctx, &lm) + if err != nil { + t.Errorf("update should not have returned error; err=%v", err) + } + + // monitoring console + err = client.Get(ctx, namespacedName, &mc) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + mc.Spec.Image = "splunk/splunk:latest" + err = client.Update(ctx, &mc) + if err != nil { + t.Errorf("update should not have returned error; err=%v", err) + } + + // indexer cluster console + err = client.Get(ctx, namespacedName, &idx) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + idx.Spec.Image = "splunk/splunk:latest" + err = client.Update(ctx, &idx) + if err != nil { + t.Errorf("update should not have returned error; err=%v", err) + } + + // searchhead cluster console + err = client.Get(ctx, namespacedName, &shc) + if err != nil { + t.Errorf("get should not have returned error; err=%v", err) + } + shc.Spec.Image = "splunk/splunk:latest" + err = client.Update(ctx, &shc) + if err != nil { + t.Errorf("update should not have returned error; err=%v", err) + } + + lm.Status.TelAppInstalled = true + _, err = ApplyLicenseManager(ctx, client, &lm) + if err != nil { + t.Errorf("ApplyLicenseManager after update should not have returned error; err=%v", err) + } + + lm.Status.TelAppInstalled = true + _, err = ApplyLicenseManager(ctx, client, &lm) + if err != nil { + t.Errorf("ApplyLicenseManager after update should not have returned error; err=%v", err) + } + + cm.Status.TelAppInstalled = true + _, err = ApplyClusterManager(ctx, client, &cm) + if err != nil { + t.Errorf("applyClusterManager after update should not have returned error; err=%v", err) + } + _, err = ApplyMonitoringConsole(ctx, client, &mc) + if err != nil { + t.Errorf("applyMonitoringConsole after update should not have returned error; err=%v", err) + } + + shc.Status.TelAppInstalled = true + _, err = ApplySearchHeadCluster(ctx, client, &shc) + if err != nil { + t.Errorf("applySearchHeadCluster after update should not have returned error; err=%v", err) + } + _, err = ApplyIndexerClusterManager(ctx, client, &idx) + if err != nil { + t.Errorf("ApplyIndexerClusterManager after update should not have returned error; err=%v", err) + } + newImage := "splunk/splunk:latest" + // create pods for license manager + createPods(t, ctx, client, "license-manager", fmt.Sprintf("splunk-%s-license-manager-0", lm.Name), lm.Namespace, newImage) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-license-manager", lm.Name), lm.Namespace) + lm.Status.TelAppInstalled = true + + // create pods for cluster manager + createPods(t, ctx, client, "cluster-manager", fmt.Sprintf("splunk-%s-cluster-manager-0", cm.Name), cm.Namespace, cm.Spec.Image) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-cluster-manager", cm.Name), cm.Namespace) + cm.Status.TelAppInstalled = true + + // create pods for indexer cluster + createPods(t, ctx, client, "indexer", fmt.Sprintf("splunk-%s-indexer-0", idx.Name), idx.Namespace, newImage) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-indexer", idx.Name), idx.Namespace) + + // create pods for cluster manager + createPods(t, ctx, client, "monitoring-console", fmt.Sprintf("splunk-%s-monitoring-console-0", lm.Name), lm.Namespace, newImage) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-monitoring-console", lm.Name), lm.Namespace) + + // create pods for cluster manager + createPods(t, ctx, client, "search-head", fmt.Sprintf("splunk-%s-search-head-0", shc.Name), shc.Namespace, newImage) + createPods(t, ctx, client, "search-head", fmt.Sprintf("splunk-%s-search-head-1", shc.Name), shc.Namespace, newImage) + createPods(t, ctx, client, "search-head", fmt.Sprintf("splunk-%s-search-head-2", shc.Name), shc.Namespace, newImage) + updateStatefulSetsInTest(t, ctx, client, 3, fmt.Sprintf("splunk-%s-search-head", shc.Name), shc.Namespace) + createPods(t, ctx, client, "deployer", fmt.Sprintf("splunk-%s-deployer-0", shc.Name), shc.Namespace, newImage) + updateStatefulSetsInTest(t, ctx, client, 1, fmt.Sprintf("splunk-%s-deployer", shc.Name), shc.Namespace) + shc.Status.TelAppInstalled = true + + lm.Status.TelAppInstalled = true + _, err = ApplyLicenseManager(ctx, client, &lm) + if err != nil { + t.Errorf("ApplyLicenseManager after update should not have returned error; err=%v", err) + } + + cm.Status.TelAppInstalled = true + _, err = ApplyClusterManager(ctx, client, &cm) + if err != nil { + t.Errorf("applyClusterManager after update should not have returned error; err=%v", err) + } + + cm.Status.TelAppInstalled = true + _, err = ApplyClusterManager(ctx, client, &cm) + if err != nil { + t.Errorf("applyClusterManager after update should not have returned error; err=%v", err) + } + + _, err = ApplyMonitoringConsole(ctx, client, &mc) + if err != nil { + t.Errorf("applyMonitoringConsole after update should not have returned error; err=%v", err) + } + + _, err = ApplyMonitoringConsole(ctx, client, &mc) + if err != nil { + t.Errorf("applyMonitoringConsole after update should not have returned error; err=%v", err) + } + + shc.Status.TelAppInstalled = true + _, err = ApplySearchHeadCluster(ctx, client, &shc) + if err != nil { + t.Errorf("applySearchHeadCluster after update should not have returned error; err=%v", err) + } + + shc.Status.TelAppInstalled = true + _, err = ApplySearchHeadCluster(ctx, client, &shc) + if err != nil { + t.Errorf("applySearchHeadCluster after update should not have returned error; err=%v", err) + } + + _, err = ApplyIndexerClusterManager(ctx, client, &idx) + if err != nil { + t.Errorf("ApplyIndexerClusterManager after update should not have returned error; err=%v", err) + } + +} + +func createPods(t *testing.T, ctx context.Context, client common.ControllerClient, crtype, name, namespace, image string) { + stpod := &corev1.Pod{} + namespacesName := types.NamespacedName{ + Name: name, + Namespace: namespace, + } + err := client.Get(ctx, namespacesName, stpod) + if err != nil && k8serrors.IsNotFound(err) { + // create pod + stpod = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + Labels: map[string]string{ + "app.kubernetes.io/managed-by": "splunk-operator", + "app.kubernetes.io/component": crtype, + "app.kubernetes.io/name": crtype, + "app.kubernetes.io/part-of": fmt.Sprintf("splunk-test-%s", crtype), + "app.kubernetes.io/instance": fmt.Sprintf("splunk-test-%s", crtype), + }, + Annotations: map[string]string{ + "traffic.sidecar.istio.io/excludeOutboundPorts": "8089,8191,9997", + "traffic.sidecar.istio.io/includeInboundPorts": "8000", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "splunk", + Image: image, + Env: []corev1.EnvVar{ + { + Name: "test", + Value: "test", + }, + }, + Ports: []corev1.ContainerPort{ + { + Name: "http-splunkweb", + HostPort: 0, + ContainerPort: 8000, + Protocol: "TCP", + HostIP: "", + }, + { + Name: "https-splunkd", + HostPort: 0, + ContainerPort: 8089, + Protocol: "TCP", + HostIP: "", + }, + }, + }, + }, + }, + } + // simulate create stateful set + err := client.Create(ctx, stpod) + if err != nil { + t.Errorf("Unexpected create pod failed %v", err) + debug.PrintStack() + } + } else if err != nil { + t.Errorf("Unexpected erro while get pod %v", err) + debug.PrintStack() + } + if stpod.Spec.Containers[0].Image != image { + stpod.Spec.Containers[0].Image = image + err := client.Update(ctx, stpod) + if err != nil { + t.Errorf("Unexpected create pod failed %v", err) + debug.PrintStack() + } + } + + // update statefulset + stpod.Status.Phase = corev1.PodRunning + stpod.Status.ContainerStatuses = []corev1.ContainerStatus{ + { + Image: image, + Name: "splunk", + Ready: true, + }, + } + err = client.Status().Update(ctx, stpod) + if err != nil { + t.Errorf("Unexpected update pod %v", err) + debug.PrintStack() + } +} + +func updateStatefulSetsInTest(t *testing.T, ctx context.Context, client common.ControllerClient, replicas int32, name, namespace string) { + stNamespacedName := types.NamespacedName{ + Name: name, + Namespace: namespace, + } + statefulset := &appsv1.StatefulSet{} + err := client.Get(ctx, stNamespacedName, statefulset) + if err != nil { + t.Errorf("Unexpected get cluster manager %v", err) + debug.PrintStack() + } + // update statefulset + statefulset.Status.ReadyReplicas = replicas + statefulset.Status.Replicas = replicas + statefulset.Status.CurrentReplicas = replicas + statefulset.Status.AvailableReplicas = replicas + err = client.Status().Update(ctx, statefulset) + if err != nil { + t.Errorf("Unexpected update statefulset %v", err) + debug.PrintStack() + } +} diff --git a/pkg/splunk/enterprise/util.go b/pkg/splunk/enterprise/util.go index ec9199f4b..7d3bd2b59 100644 --- a/pkg/splunk/enterprise/util.go +++ b/pkg/splunk/enterprise/util.go @@ -2272,3 +2272,41 @@ func getApplicablePodNameForK8Probes(cr splcommon.MetaObject, ordinalIdx int32) } return fmt.Sprintf("splunk-%s-%s-%d", cr.GetName(), podType, ordinalIdx) } + +// getCurrentImage gets the image of the statefulset, returns the image, and error if something goes wrong +func getCurrentImage(ctx context.Context, c splcommon.ControllerClient, cr splcommon.MetaObject, instanceType InstanceType) (string, error) { + namespacedName := types.NamespacedName{ + Namespace: cr.GetNamespace(), + Name: GetSplunkStatefulsetName(instanceType, cr.GetName()), + } + statefulSet := &appsv1.StatefulSet{} + err := c.Get(ctx, namespacedName, statefulSet) + if err != nil { + return "", err + } + + if len(statefulSet.Spec.Template.Spec.Containers) > 0 { + return statefulSet.Spec.Template.Spec.Containers[0].Image, nil + } + return "", fmt.Errorf("Unable to get image from statefulset of type %s.", instanceType.ToString()) +} + +// changeAnnotations updates the splunk/image-tag field to trigger the reconcile loop, and returns error if something is wrong +func changeAnnotations(ctx context.Context, c splcommon.ControllerClient, image string, cr splcommon.MetaObject) error { + annotations := cr.GetAnnotations() + if annotations == nil { + annotations = map[string]string{} + } + if _, ok := annotations["splunk/image-tag"]; ok { + if annotations["splunk/image-tag"] == image { + return nil + } + } + + // create/update the checkUpdateImage annotation field + annotations["splunk/image-tag"] = image + + cr.SetAnnotations(annotations) + err := c.Update(ctx, cr) + return err +} diff --git a/pkg/splunk/enterprise/util_test.go b/pkg/splunk/enterprise/util_test.go index 014171ddd..ba9aa8f8a 100644 --- a/pkg/splunk/enterprise/util_test.go +++ b/pkg/splunk/enterprise/util_test.go @@ -3149,3 +3149,43 @@ func TestGetLicenseMasterURL(t *testing.T) { t.Errorf("Expected a valid return value") } } +func TestGetCurrentImage(t *testing.T) { + + ctx := context.TODO() + current := enterpriseApi.ClusterManager{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + Spec: enterpriseApi.ClusterManagerSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "Always", + Image: "splunk/splunk:latest", + }, + Volumes: []corev1.Volume{}, + }, + }, + } + builder := fake.NewClientBuilder() + client := builder.Build() + utilruntime.Must(enterpriseApi.AddToScheme(clientgoscheme.Scheme)) + + err := client.Create(ctx, ¤t) + _, err = ApplyClusterManager(ctx, client, ¤t) + if err != nil { + t.Errorf("applyClusterManager should not have returned error; err=%v", err) + } + + instanceType := SplunkClusterManager + + image, err := getCurrentImage(ctx, client, ¤t, instanceType) + + if err != nil { + t.Errorf("Unexpected getCurrentImage error %v", err) + } + if image != current.Spec.Image { + t.Errorf("getCurrentImage does not return the current statefulset image") + } + +} diff --git a/test/appframework_aws/c3/appframework_aws_test.go b/test/appframework_aws/c3/appframework_aws_test.go index 86e89a172..70d309bf9 100644 --- a/test/appframework_aws/c3/appframework_aws_test.go +++ b/test/appframework_aws/c3/appframework_aws_test.go @@ -57,6 +57,7 @@ var _ = Describe("c3appfw test", func() { name := fmt.Sprintf("%s-%s", "master"+testenvInstance.GetName(), testenv.RandomDNSName(3)) testcaseEnvInst, err = testenv.NewDefaultTestCaseEnv(testenvInstance.GetKubeClient(), name) Expect(err).To(Succeed(), "Unable to create testcaseenv") + testenv.SpecifiedTestTimeout = 4000 deployment, err = testcaseEnvInst.NewDeployment(testenv.RandomDNSName(3)) Expect(err).To(Succeed(), "Unable to create deployment") }) @@ -189,12 +190,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -270,12 +271,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -409,12 +410,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -478,12 +479,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -588,12 +589,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -854,12 +855,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -903,12 +904,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1043,12 +1044,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1107,12 +1108,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1250,12 +1251,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1315,12 +1316,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1413,12 +1414,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1539,12 +1540,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1601,12 +1602,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1751,12 +1752,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1800,12 +1801,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1976,12 +1977,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2052,12 +2053,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2331,6 +2332,9 @@ var _ = Describe("c3appfw test", func() { // Wait for polling interval to pass testenv.WaitForAppInstall(ctx, deployment, testcaseEnvInst, deployment.GetName(), cm.Kind, appSourceNameIdxc, appFileList) + // Ensure Search Head Cluster go to Ready phase + testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) @@ -2341,9 +2345,6 @@ var _ = Describe("c3appfw test", func() { testcaseEnvInst.Log.Info(fmt.Sprintf("Verify all apps %v are installed on indexers", appList)) testenv.VerifyAppInstalled(ctx, deployment, testcaseEnvInst, testcaseEnvInst.GetName(), idxcPodNames, appList, true, "enabled", false, true) - // Ensure Search Head Cluster go to Ready phase - testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) - // Wait for polling interval to pass testenv.WaitForAppInstall(ctx, deployment, testcaseEnvInst, deployment.GetName()+"-shc", shc.Kind, appSourceNameShc, appFileList) @@ -2420,12 +2421,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2514,12 +2515,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2599,12 +2600,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2748,12 +2749,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2842,12 +2843,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2935,12 +2936,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -3019,12 +3020,12 @@ var _ = Describe("c3appfw test", func() { testcaseEnvInst.Log.Info("Checking isDeploymentInProgress Flag") testenv.VerifyIsDeploymentInProgressFlagIsSet(ctx, deployment, testcaseEnvInst, shc.Name, shc.Kind) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) }) @@ -3197,12 +3198,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) diff --git a/test/appframework_aws/c3/manager_appframework_test.go b/test/appframework_aws/c3/manager_appframework_test.go index 96fd1efd0..38dc33dae 100644 --- a/test/appframework_aws/c3/manager_appframework_test.go +++ b/test/appframework_aws/c3/manager_appframework_test.go @@ -187,12 +187,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -268,12 +268,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -304,6 +304,147 @@ var _ = Describe("c3appfw test", func() { }) }) + Context("Single Site Indexer Cluster with Search Head Cluster (C3) and App Framework and Image Upgrade", func() { + It("smoke, c3, managerappframeworkc3t, appframework: can deploy a C3 SVA with App Framework enabled, install apps then upgrade the image and apps", func() { + + //################## SETUP #################### + + // Download License File + downloadDir := "licenseFolder" + switch testenv.ClusterProvider { + case "eks": + licenseFilePath, err := testenv.DownloadLicenseFromS3Bucket() + Expect(err).To(Succeed(), "Unable to download license file from S3") + // Create License Config Map + testcaseEnvInst.CreateLicenseConfigMap(licenseFilePath) + case "azure": + licenseFilePath, err := testenv.DownloadLicenseFromAzure(ctx, downloadDir) + Expect(err).To(Succeed(), "Unable to download license file from Azure") + // Create License Config Map + testcaseEnvInst.CreateLicenseConfigMap(licenseFilePath) + default: + fmt.Printf("Unable to download license file") + testcaseEnvInst.Log.Info(fmt.Sprintf("Unable to download license file with Cluster Provider set as %v", testenv.ClusterProvider)) + } + + // Upload V1 apps to S3 for Monitoring Console + oldImage := "splunk/splunk:9.0.3-a2" + newImage := "splunk/splunk:9.0.5" + + lm, err := deployment.DeployLicenseManager(ctx, deployment.GetName()) + cm, err := deployment.DeployClusterManager(ctx, deployment.GetName(), lm.GetName(), "", "") + + mcSpec := enterpriseApi.MonitoringConsoleSpec{ + CommonSplunkSpec: enterpriseApi.CommonSplunkSpec{ + Spec: enterpriseApi.Spec{ + ImagePullPolicy: "IfNotPresent", + }, + Volumes: []corev1.Volume{}, + ClusterManagerRef: corev1.ObjectReference{ + Name: cm.GetName(), + }, + }, + } + mcName := deployment.GetName() + mc, err := deployment.DeployMonitoringConsoleWithGivenSpec(ctx, testcaseEnvInst.GetName(), mcName, mcSpec) + Expect(err).To(Succeed(), "Unable to deploy Monitoring Console") + + shcName := fmt.Sprintf("%s-shc", deployment.GetName()) + idxName := fmt.Sprintf("%s-idxc", deployment.GetName()) + shc, err := deployment.DeploySearchHeadCluster(ctx, shcName, cm.GetName(), lm.GetName(), "", mcName) + idxc, err := deployment.DeployIndexerCluster(ctx, idxName, lm.GetName(), 3, cm.GetName(), "") + + // Wait for License Manager to be in READY phase + testenv.LicenseManagerReady(ctx, deployment, testcaseEnvInst) + + // Ensure Cluster Manager goes to Ready phase + testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) + + // Ensure Monitoring Console goes to Ready phase + testenv.VerifyMonitoringConsoleReady(ctx, deployment, deployment.GetName(), mc, testcaseEnvInst) + + // // Ensure Search Head Cluster go to Ready phase + testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + + // // Verify Monitoring Console is ready and stays in ready state + testenv.VerifyMonitoringConsoleReady(ctx, deployment, deployment.GetName(), mc, testcaseEnvInst) + + // // Verify no SH in disconnected status is present on CM + testenv.VerifyNoDisconnectedSHPresentOnCM(ctx, deployment, testcaseEnvInst) + + // Get Pod age to check for pod resets later + splunkPodAge := testenv.GetPodsStartTime(testcaseEnvInst.GetName()) + + // ############ Verify livenessProbe and readinessProbe config object and scripts############ + testcaseEnvInst.Log.Info("Get config map for livenessProbe and readinessProbe") + ConfigMapName := enterprise.GetProbeConfigMapName(testcaseEnvInst.GetName()) + _, err = testenv.GetConfigMap(ctx, deployment, testcaseEnvInst.GetName(), ConfigMapName) + Expect(err).To(Succeed(), "Unable to get config map for livenessProbe and readinessProbe", "ConfigMap name", ConfigMapName) + scriptsNames := []string{enterprise.GetLivenessScriptName(), enterprise.GetReadinessScriptName(), enterprise.GetStartupScriptName()} + allPods := testenv.DumpGetPods(testcaseEnvInst.GetName()) + testenv.VerifyFilesInDirectoryOnPod(ctx, deployment, testcaseEnvInst, testcaseEnvInst.GetName(), allPods, scriptsNames, enterprise.GetProbeMountDirectory(), false, true) + + // Verify no pods reset by checking the pod age + testenv.VerifyNoPodReset(ctx, deployment, testcaseEnvInst, testcaseEnvInst.GetName(), splunkPodAge, nil) + + //############### UPGRADE IMAGE ################ + + // Update LM Image + + testcaseEnvInst.Log.Info("Upgrading the License Manager Image", "Current Image", oldImage, "New Image", newImage) + lm.Spec.Image = newImage + err = deployment.UpdateCR(ctx, lm) + Expect(err).To(Succeed(), "Failed upgrade License Manager image") + + // Update CM image + + testcaseEnvInst.Log.Info("Upgrading the Cluster Manager Image", "Current Image", oldImage, "New Image", newImage) + cm.Spec.Image = newImage + err = deployment.UpdateCR(ctx, cm) + Expect(err).To(Succeed(), "Failed upgrade Cluster Manager image") + + // Update MC image + + testcaseEnvInst.Log.Info("Upgrading the Monitoring Console Image", "Current Image", oldImage, "New Image", newImage) + mc.Spec.Image = newImage + err = deployment.UpdateCR(ctx, mc) + Expect(err).To(Succeed(), "Failed upgrade Monitoring Console image") + + // Update SHC image + + testcaseEnvInst.Log.Info("Upgrading the Search Head Cluster Image", "Current Image", oldImage, "New Image", newImage) + shc.Spec.Image = newImage + err = deployment.UpdateCR(ctx, shc) + Expect(err).To(Succeed(), "Failed upgrade Search Head Cluster image") + + // // Update IDXC image + + testcaseEnvInst.Log.Info("Upgrading the Indexer Cluster Image", "Current Image", oldImage, "New Image", newImage) + idxc.Spec.Image = newImage + err = deployment.UpdateCR(ctx, idxc) + Expect(err).To(Succeed(), "Failed upgrade Indexer Cluster image") + + // Ensure Cluster Manager goes to Ready phase + testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) + + // Wait for License Manager to be in READY phase + testenv.LicenseManagerReady(ctx, deployment, testcaseEnvInst) + + // // Verify Monitoring Console is ready and stays in ready state + testenv.VerifyMonitoringConsoleReady(ctx, deployment, deployment.GetName(), mc, testcaseEnvInst) + + // // Ensure Search Head Cluster go to Ready phase + testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + + // // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + + }) + }) + Context("Single Site Indexer Cluster with Search Head Cluster (C3) with App Framework", func() { It("smoke, c3, managerappframeworkc3, appframework: can deploy a C3 SVA with App Framework enabled, install apps then downgrade them", func() { @@ -407,12 +548,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -476,12 +617,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -586,12 +727,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -852,12 +993,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -901,12 +1042,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1041,12 +1182,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1105,12 +1246,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1248,12 +1389,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1313,12 +1454,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1411,12 +1552,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1537,12 +1678,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1599,12 +1740,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1749,12 +1890,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1798,12 +1939,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1974,12 +2115,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2050,12 +2191,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2217,7 +2358,7 @@ var _ = Describe("c3appfw test", func() { testenv.VerifyAppInstalled(ctx, deployment, testcaseEnvInst, testcaseEnvInst.GetName(), deployerPod, appList, true, "enabled", false, false) }) }) - + // Vivek need testing Context("Single Site Indexer Cluster with Search Head Cluster (C3) and App Framework", func() { It("integration, c3, managerappframeworkc3, appframework: can deploy a C3, add new apps to app source while install is in progress and have all apps installed cluster-wide", func() { @@ -2352,7 +2493,7 @@ var _ = Describe("c3appfw test", func() { }) }) - + // Vivek need testing Context("Single Site Indexer Cluster with Search Head Cluster (C3) and App Framework", func() { It("integration, c3, managerappframeworkc3, appframework: can deploy a C3 SVA with App Framework enabled and reset operator pod while app install is in progress", func() { @@ -2418,12 +2559,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2512,12 +2653,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2597,12 +2738,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2746,12 +2887,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2840,12 +2981,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2933,12 +3074,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -3017,12 +3158,12 @@ var _ = Describe("c3appfw test", func() { testcaseEnvInst.Log.Info("Checking isDeploymentInProgress Flag") testenv.VerifyIsDeploymentInProgressFlagIsSet(ctx, deployment, testcaseEnvInst, shc.Name, shc.Kind) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) }) @@ -3195,12 +3336,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) diff --git a/test/appframework_aws/m4/appframework_aws_test.go b/test/appframework_aws/m4/appframework_aws_test.go index 1549f92e1..c7c6c6e8d 100644 --- a/test/appframework_aws/m4/appframework_aws_test.go +++ b/test/appframework_aws/m4/appframework_aws_test.go @@ -2422,15 +2422,15 @@ var _ = Describe("m4appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) + // Ensure Search Head Cluster go to Ready phase + testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure the Indexers of all sites go to Ready phase testenv.IndexersReady(ctx, deployment, testcaseEnvInst, siteCount) // Ensure Indexer Cluster configured as Multisite testenv.IndexerClusterMultisiteStatus(ctx, deployment, testcaseEnvInst, siteCount) - // Ensure Search Head Cluster go to Ready phase - testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) - // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) diff --git a/test/appframework_aws/m4/manager_appframework_test.go b/test/appframework_aws/m4/manager_appframework_test.go index 8f44be55b..5310000cb 100644 --- a/test/appframework_aws/m4/manager_appframework_test.go +++ b/test/appframework_aws/m4/manager_appframework_test.go @@ -2421,15 +2421,15 @@ var _ = Describe("m4appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) + // Ensure Search Head Cluster go to Ready phase + testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure the Indexers of all sites go to Ready phase testenv.IndexersReady(ctx, deployment, testcaseEnvInst, siteCount) // Ensure Indexer Cluster configured as Multisite testenv.IndexerClusterMultisiteStatus(ctx, deployment, testcaseEnvInst, siteCount) - // Ensure Search Head Cluster go to Ready phase - testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) - // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2517,12 +2517,12 @@ var _ = Describe("m4appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure the Indexers of all sites go to Ready phase - testenv.IndexersReady(ctx, deployment, testcaseEnvInst, siteCount) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure the Indexers of all sites go to Ready phase + testenv.IndexersReady(ctx, deployment, testcaseEnvInst, siteCount) + // Get Pod age to check for pod resets later splunkPodAge := testenv.GetPodsStartTime(testcaseEnvInst.GetName()) diff --git a/test/appframework_az/c3/appframework_azure_test.go b/test/appframework_az/c3/appframework_azure_test.go index c8eb33545..97bcbea77 100644 --- a/test/appframework_az/c3/appframework_azure_test.go +++ b/test/appframework_az/c3/appframework_azure_test.go @@ -187,12 +187,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -261,12 +261,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -400,12 +400,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -470,12 +470,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -580,12 +580,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -828,12 +828,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -878,12 +878,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1013,12 +1013,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1063,12 +1063,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1197,12 +1197,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1262,12 +1262,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1408,12 +1408,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1473,12 +1473,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1572,12 +1572,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1698,12 +1698,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1761,12 +1761,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1911,12 +1911,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1961,12 +1961,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2137,12 +2137,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2214,12 +2214,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2585,12 +2585,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2680,12 +2680,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2766,12 +2766,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2918,12 +2918,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -3008,12 +3008,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -3102,12 +3102,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -3186,12 +3186,12 @@ var _ = Describe("c3appfw test", func() { testcaseEnvInst.Log.Info("Checking isDeploymentInProgress Flag") testenv.VerifyIsDeploymentInProgressFlagIsSet(ctx, deployment, testcaseEnvInst, shc.Name, shc.Kind) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) }) diff --git a/test/appframework_az/c3/manager_appframework_azure_test.go b/test/appframework_az/c3/manager_appframework_azure_test.go index 5197ed894..503b3cce3 100644 --- a/test/appframework_az/c3/manager_appframework_azure_test.go +++ b/test/appframework_az/c3/manager_appframework_azure_test.go @@ -185,12 +185,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -259,12 +259,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -398,12 +398,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -468,12 +468,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -578,12 +578,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -826,12 +826,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -876,12 +876,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1011,12 +1011,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1061,12 +1061,12 @@ var _ = Describe("c3appfw test", func() { // // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1196,12 +1196,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1261,12 +1261,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1407,12 +1407,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1473,12 +1473,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1572,12 +1572,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1698,12 +1698,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1761,12 +1761,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1911,12 +1911,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -1961,12 +1961,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2137,12 +2137,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2214,12 +2214,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2585,12 +2585,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2680,12 +2680,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2766,12 +2766,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -2918,12 +2918,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -3008,12 +3008,12 @@ var _ = Describe("c3appfw test", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -3102,12 +3102,12 @@ var _ = Describe("c3appfw test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) @@ -3186,12 +3186,12 @@ var _ = Describe("c3appfw test", func() { testcaseEnvInst.Log.Info("Checking isDeploymentInProgress Flag") testenv.VerifyIsDeploymentInProgressFlagIsSet(ctx, deployment, testcaseEnvInst, shc.Name, shc.Kind) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) }) diff --git a/test/custom_resource_crud/custom_resource_crud_c3_test.go b/test/custom_resource_crud/custom_resource_crud_c3_test.go index d020c8a72..b847e517d 100644 --- a/test/custom_resource_crud/custom_resource_crud_c3_test.go +++ b/test/custom_resource_crud/custom_resource_crud_c3_test.go @@ -74,12 +74,12 @@ var _ = Describe("Crcrud test for SVA C3", func() { // Ensure that the Cluster Master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Deploy Monitoring Console CRD mc, err := deployment.DeployMonitoringConsole(ctx, mcRef, "") Expect(err).To(Succeed(), "Unable to deploy Monitoring Console One instance") diff --git a/test/custom_resource_crud/manager_custom_resource_crud_c3_test.go b/test/custom_resource_crud/manager_custom_resource_crud_c3_test.go index b30b4ce02..a86a58322 100644 --- a/test/custom_resource_crud/manager_custom_resource_crud_c3_test.go +++ b/test/custom_resource_crud/manager_custom_resource_crud_c3_test.go @@ -75,12 +75,12 @@ var _ = Describe("Crcrud test for SVA C3", func() { // Ensure that the Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Deploy Monitoring Console CRD mc, err := deployment.DeployMonitoringConsole(ctx, mcRef, "") Expect(err).To(Succeed(), "Unable to deploy Monitoring Console One instance") diff --git a/test/delete_cr/deletecr_test.go b/test/delete_cr/deletecr_test.go index f0e94c81a..300d3cd1f 100644 --- a/test/delete_cr/deletecr_test.go +++ b/test/delete_cr/deletecr_test.go @@ -94,12 +94,12 @@ var _ = Describe("DeleteCR test", func() { // Ensure Cluster Manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure Indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + idxc := &enterpriseApi.IndexerCluster{} idxcName := deployment.GetName() + "-idxc" err = deployment.GetInstance(ctx, idxcName, idxc) diff --git a/test/licensemanager/manager_lm_c3_test.go b/test/licensemanager/manager_lm_c3_test.go index 83b954169..af80f1fd2 100644 --- a/test/licensemanager/manager_lm_c3_test.go +++ b/test/licensemanager/manager_lm_c3_test.go @@ -85,12 +85,12 @@ var _ = Describe("Licensemanager test", func() { // Ensure that the cluster-manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Deploy Monitoring Console CRD mc, err := deployment.DeployMonitoringConsole(ctx, mcRef, deployment.GetName()) Expect(err).To(Succeed(), "Unable to deploy Monitoring Console") diff --git a/test/licensemaster/lm_c3_test.go b/test/licensemaster/lm_c3_test.go index f93d917ed..986bb2d1f 100644 --- a/test/licensemaster/lm_c3_test.go +++ b/test/licensemaster/lm_c3_test.go @@ -86,12 +86,12 @@ var _ = Describe("licensemaster test", func() { // Ensure that the cluster-master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Deploy Monitoring Console CRD mc, err := deployment.DeployMonitoringConsole(ctx, mcRef, deployment.GetName()) Expect(err).To(Succeed(), "Unable to deploy Monitoring Console") diff --git a/test/monitoring_console/manager_monitoring_console_test.go b/test/monitoring_console/manager_monitoring_console_test.go index d38dc3ebb..42af80f06 100644 --- a/test/monitoring_console/manager_monitoring_console_test.go +++ b/test/monitoring_console/manager_monitoring_console_test.go @@ -451,12 +451,12 @@ var _ = Describe("Monitoring Console test", func() { // Ensure that the cluster-manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // wait for custom resource resource version to change testenv.VerifyCustomResourceVersionChanged(ctx, deployment, testcaseEnvInst, mc, resourceVersion) @@ -626,12 +626,12 @@ var _ = Describe("Monitoring Console test", func() { // Ensure that the cluster-manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // wait for custom resource resource version to change testenv.VerifyCustomResourceVersionChanged(ctx, deployment, testcaseEnvInst, mc, resourceVersion) diff --git a/test/monitoring_console/monitoring_console_test.go b/test/monitoring_console/monitoring_console_test.go index b6f80e0ea..99375cb59 100644 --- a/test/monitoring_console/monitoring_console_test.go +++ b/test/monitoring_console/monitoring_console_test.go @@ -94,12 +94,12 @@ var _ = Describe("Monitoring Console test", func() { // Ensure that the cluster-master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // wait for custom resource resource version to change testenv.VerifyCustomResourceVersionChanged(ctx, deployment, testcaseEnvInst, mc, resourceVersion) @@ -269,12 +269,12 @@ var _ = Describe("Monitoring Console test", func() { // Ensure that the cluster-master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // wait for custom resource resource version to change testenv.VerifyCustomResourceVersionChanged(ctx, deployment, testcaseEnvInst, mc, resourceVersion) diff --git a/test/run-tests.sh b/test/run-tests.sh index 27e01ac29..6eabde8bc 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -22,7 +22,7 @@ if [ -n "${PRIVATE_REGISTRY}" ]; then PRIVATE_SPLUNK_ENTERPRISE_IMAGE=${PRIVATE_REGISTRY}/${SPLUNK_ENTERPRISE_IMAGE} echo "docker images -q ${SPLUNK_OPERATOR_IMAGE}" # Don't pull splunk operator if exists locally since we maybe building it locally - if [ -z $(docker images -q ${SPLUNK_OPERATOR_IMAGE}) ]; then + if [ -z $(docker images -q ${SPLUNK_OPERATOR_IMAGE}) ]; then docker pull ${SPLUNK_OPERATOR_IMAGE} if [ $? -ne 0 ]; then echo "Unable to pull ${SPLUNK_OPERATOR_IMAGE}. Exiting..." @@ -55,7 +55,7 @@ if [ -n "${PRIVATE_REGISTRY}" ]; then docker images fi -if [ "${DEPLOYMENT_TYPE}" == "helm" ]; then +if [ "${DEPLOYMENT_TYPE}" == "helm" ]; then echo "Installing Splunk Operator using Helm charts" helm uninstall splunk-operator -n splunk-operator if [ "${CLUSTER_WIDE}" != "true" ]; then @@ -63,10 +63,10 @@ if [ "${DEPLOYMENT_TYPE}" == "helm" ]; then else helm install splunk-operator --create-namespace --namespace splunk-operator --set splunkOperator.image.repository=${PRIVATE_SPLUNK_OPERATOR_IMAGE} --set image.repository=${PRIVATE_SPLUNK_ENTERPRISE_IMAGE} helm-chart/splunk-operator fi -elif [ "${CLUSTER_WIDE}" != "true" ]; then +elif [ "${CLUSTER_WIDE}" != "true" ]; then # Install the CRDs echo "Installing enterprise CRDs..." - make kustomize + make kustomize make uninstall bin/kustomize build config/crd | kubectl create -f - else @@ -79,7 +79,7 @@ if [ $? -ne 0 ]; then exit 1 fi -if [ "${CLUSTER_WIDE}" == "true" ]; then +if [ "${CLUSTER_WIDE}" == "true" ]; then echo "wait for operator pod to be ready..." # sleep before checking for deployment, in slow clusters deployment call may not even started # in those cases, kubectl will fail with error: no matching resources found @@ -98,14 +98,14 @@ if [ -z "$rc" ]; then go get github.com/onsi/gomega/... go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo@latest -fi +fi echo "Running test using number of nodes: ${NUM_NODES}" echo "Running test using these images: ${PRIVATE_SPLUNK_OPERATOR_IMAGE} and ${PRIVATE_SPLUNK_ENTERPRISE_IMAGE}..." -# Check if test focus is set +# Check if test focus is set if [[ -z "${TEST_FOCUS}" ]]; then TEST_TO_RUN="${TEST_REGEX}" echo "Test focus not set running smoke test by default :: ${TEST_TO_RUN}" @@ -191,5 +191,5 @@ fi echo "Skipping following test :: ${TEST_TO_SKIP}" # Running only smoke test cases by default or value passed through TEST_FOCUS env variable. To run different test packages add/remove path from focus argument or TEST_FOCUS variable -echo "ginkgo --junit-report=inttest.xml -vv --keep-going --trace -r --timeout=3h -nodes=${CLUSTER_NODES} --focus="${TEST_TO_RUN}" --skip="${TEST_TO_SKIP}" --output-interceptor-mode=none --cover ${topdir}/test/ -- -commit-hash=${COMMIT_HASH} -operator-image=${PRIVATE_SPLUNK_OPERATOR_IMAGE} -splunk-image=${PRIVATE_SPLUNK_ENTERPRISE_IMAGE} -cluster-wide=${CLUSTER_WIDE}" -ginkgo --junit-report=inttest-junit.xml --output-dir=`pwd` -vv --keep-going --trace -r --timeout=3h -nodes=${CLUSTER_NODES} --focus="${TEST_TO_RUN}" --skip="${TEST_TO_SKIP}" --output-interceptor-mode=none --cover ${topdir}/test/ -- -commit-hash=${COMMIT_HASH} -operator-image=${PRIVATE_SPLUNK_OPERATOR_IMAGE} -splunk-image=${PRIVATE_SPLUNK_ENTERPRISE_IMAGE} -cluster-wide=${CLUSTER_WIDE} \ No newline at end of file +echo "ginkgo --junit-report=inttest.xml -vv --keep-going --trace -r --timeout=7h -nodes=${CLUSTER_NODES} --focus="${TEST_TO_RUN}" --skip="${TEST_TO_SKIP}" --output-interceptor-mode=none --cover ${topdir}/test/ -- -commit-hash=${COMMIT_HASH} -operator-image=${PRIVATE_SPLUNK_OPERATOR_IMAGE} -splunk-image=${PRIVATE_SPLUNK_ENTERPRISE_IMAGE} -cluster-wide=${CLUSTER_WIDE}" +ginkgo --junit-report=inttest-junit.xml --output-dir=`pwd` -vv --keep-going --trace -r --timeout=7h -nodes=${CLUSTER_NODES} --focus="${TEST_TO_RUN}" --skip="${TEST_TO_SKIP}" --output-interceptor-mode=none --cover ${topdir}/test/ -- -commit-hash=${COMMIT_HASH} -operator-image=${PRIVATE_SPLUNK_OPERATOR_IMAGE} -splunk-image=${PRIVATE_SPLUNK_ENTERPRISE_IMAGE} -cluster-wide=${CLUSTER_WIDE} \ No newline at end of file diff --git a/test/secret/manager_secret_c3_test.go b/test/secret/manager_secret_c3_test.go index 0122f0ede..1c4740472 100644 --- a/test/secret/manager_secret_c3_test.go +++ b/test/secret/manager_secret_c3_test.go @@ -91,12 +91,12 @@ var _ = Describe("Secret Test for SVA C3", func() { // Ensure that the cluster-manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Deploy Monitoring Console CRD mc, err := deployment.DeployMonitoringConsole(ctx, deployment.GetName(), deployment.GetName()) Expect(err).To(Succeed(), "Unable to deploy Monitoring Console One instance") @@ -134,12 +134,12 @@ var _ = Describe("Secret Test for SVA C3", func() { // Ensure that the cluster-manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // wait for custom resource resource version to change testenv.VerifyCustomResourceVersionChanged(ctx, deployment, testcaseEnvInst, mc, resourceVersion) diff --git a/test/secret/secret_c3_test.go b/test/secret/secret_c3_test.go index d10d9a3d1..2375deb5a 100644 --- a/test/secret/secret_c3_test.go +++ b/test/secret/secret_c3_test.go @@ -91,12 +91,12 @@ var _ = Describe("Secret Test for SVA C3", func() { // Ensure that the cluster-master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Deploy Monitoring Console CRD mc, err := deployment.DeployMonitoringConsole(ctx, deployment.GetName(), deployment.GetName()) Expect(err).To(Succeed(), "Unable to deploy Monitoring Console One instance") @@ -134,12 +134,12 @@ var _ = Describe("Secret Test for SVA C3", func() { // Ensure that the cluster-master goes to Ready phase testenv.ClusterMasterReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // wait for custom resource resource version to change testenv.VerifyCustomResourceVersionChanged(ctx, deployment, testcaseEnvInst, mc, resourceVersion) diff --git a/test/smoke/smoke_test.go b/test/smoke/smoke_test.go index 61ef1195b..ed8d82626 100644 --- a/test/smoke/smoke_test.go +++ b/test/smoke/smoke_test.go @@ -74,12 +74,12 @@ var _ = Describe("Smoke test", func() { // Ensure that the cluster-manager goes to Ready phase testenv.ClusterManagerReady(ctx, deployment, testcaseEnvInst) - // Ensure indexers go to Ready phase - testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) - - // Ensure search head cluster go to Ready phase + // Ensure Search Head Cluster go to Ready phase testenv.SearchHeadClusterReady(ctx, deployment, testcaseEnvInst) + // Ensure Indexers go to Ready phase + testenv.SingleSiteIndexersReady(ctx, deployment, testcaseEnvInst) + // Verify RF SF is met testenv.VerifyRFSFMet(ctx, deployment, testcaseEnvInst) }) diff --git a/test/testenv/testenv.go b/test/testenv/testenv.go index 361f14614..db8a5b139 100644 --- a/test/testenv/testenv.go +++ b/test/testenv/testenv.go @@ -46,7 +46,7 @@ const ( defaultSplunkImage = "splunk/splunk:latest" // defaultTestTimeout is the max timeout in seconds before async test failed. - defaultTestTimeout = 3000 + defaultTestTimeout = 10000 // PollInterval specifies the polling interval PollInterval = 5 * time.Second @@ -58,7 +58,7 @@ const ( ConsistentDuration = 2000 * time.Millisecond // DefaultTimeout is the max timeout before we failed. - DefaultTimeout = 5 * time.Minute + DefaultTimeout = 10 * time.Minute // SearchHeadPod Template String for search head pod SearchHeadPod = "splunk-%s-shc-search-head-%d"