From 9aa689b95b497bd0f1e82a79df5799f106414e42 Mon Sep 17 00:00:00 2001 From: akondur Date: Fri, 8 Jan 2021 14:17:50 -0800 Subject: [PATCH 1/6] Adding support to configure a custom serviceaccount per CRD --- ...erprise.splunk.com_clustermasters_crd.yaml | 4 + ...rprise.splunk.com_indexerclusters_crd.yaml | 4 + ...erprise.splunk.com_licensemasters_crd.yaml | 4 + ...ise.splunk.com_searchheadclusters_crd.yaml | 4 + ...enterprise.splunk.com_standalones_crd.yaml | 4 + ...erprise.splunk.com_clustermasters_crd.yaml | 4 + ...rprise.splunk.com_indexerclusters_crd.yaml | 4 + ...erprise.splunk.com_licensemasters_crd.yaml | 4 + ...ise.splunk.com_searchheadclusters_crd.yaml | 4 + ...enterprise.splunk.com_standalones_crd.yaml | 4 + docs/CustomResources.md | 4 +- pkg/apis/enterprise/v1beta1/common_types.go | 3 + pkg/splunk/controller/serviceaccount.go | 57 +++++++++++++++ pkg/splunk/controller/serviceaccount_test.go | 73 +++++++++++++++++++ pkg/splunk/enterprise/clustermaster_test.go | 10 +++ pkg/splunk/enterprise/configuration.go | 10 +++ pkg/splunk/enterprise/indexercluster_test.go | 11 +++ pkg/splunk/enterprise/licensemaster_test.go | 12 +++ .../enterprise/searchheadcluster_test.go | 21 ++++++ pkg/splunk/enterprise/standalone_test.go | 11 +++ pkg/splunk/test/controller.go | 2 + 21 files changed, 252 insertions(+), 2 deletions(-) create mode 100644 pkg/splunk/controller/serviceaccount.go create mode 100644 pkg/splunk/controller/serviceaccount_test.go diff --git a/deploy/crds/enterprise.splunk.com_clustermasters_crd.yaml b/deploy/crds/enterprise.splunk.com_clustermasters_crd.yaml index d02058084..b2492620f 100644 --- a/deploy/crds/enterprise.splunk.com_clustermasters_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_clustermasters_crd.yaml @@ -744,6 +744,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/deploy/crds/enterprise.splunk.com_indexerclusters_crd.yaml b/deploy/crds/enterprise.splunk.com_indexerclusters_crd.yaml index 5b0f94156..ca9fe63bc 100644 --- a/deploy/crds/enterprise.splunk.com_indexerclusters_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_indexerclusters_crd.yaml @@ -767,6 +767,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/deploy/crds/enterprise.splunk.com_licensemasters_crd.yaml b/deploy/crds/enterprise.splunk.com_licensemasters_crd.yaml index 89200ca61..4064727b9 100644 --- a/deploy/crds/enterprise.splunk.com_licensemasters_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_licensemasters_crd.yaml @@ -749,6 +749,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/deploy/crds/enterprise.splunk.com_searchheadclusters_crd.yaml b/deploy/crds/enterprise.splunk.com_searchheadclusters_crd.yaml index b189409b8..f6ce507b4 100644 --- a/deploy/crds/enterprise.splunk.com_searchheadclusters_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_searchheadclusters_crd.yaml @@ -771,6 +771,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/deploy/crds/enterprise.splunk.com_standalones_crd.yaml b/deploy/crds/enterprise.splunk.com_standalones_crd.yaml index 293f7bdfe..a3d03aab0 100644 --- a/deploy/crds/enterprise.splunk.com_standalones_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_standalones_crd.yaml @@ -763,6 +763,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_clustermasters_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_clustermasters_crd.yaml index 5c9b2adc7..3b9ae908b 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_clustermasters_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_clustermasters_crd.yaml @@ -740,6 +740,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_indexerclusters_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_indexerclusters_crd.yaml index 5b0f94156..ca9fe63bc 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_indexerclusters_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_indexerclusters_crd.yaml @@ -767,6 +767,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_licensemasters_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_licensemasters_crd.yaml index 5b2239343..555067d44 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_licensemasters_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_licensemasters_crd.yaml @@ -745,6 +745,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_searchheadclusters_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_searchheadclusters_crd.yaml index 77d75f9aa..bbe22a970 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_searchheadclusters_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_searchheadclusters_crd.yaml @@ -767,6 +767,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_standalones_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_standalones_crd.yaml index 044014cd5..3ce82b3cd 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_standalones_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_standalones_crd.yaml @@ -759,6 +759,10 @@ spec: description: Name of Scheduler to use for pod placement (defaults to “default-scheduler”) type: string + serviceAccount: + description: ServiceAccount is the service account used by the pods + deployed by the CRD + type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes services diff --git a/docs/CustomResources.md b/docs/CustomResources.md index 3506e9741..889ff68a8 100644 --- a/docs/CustomResources.md +++ b/docs/CustomResources.md @@ -79,7 +79,6 @@ configuration parameters: | resources | [ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#resourcerequirements-v1-core) | CPU and memory [compute resource requirements](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to use for each pod instance (defaults shown in example above) | | 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/) | - ## Common Spec Parameters for Splunk Enterprise Resources ```yaml @@ -99,6 +98,7 @@ spec: name: example clusterMasterRef: name: example + serviceAccount: custom-serviceaccount ``` The following additional configuration parameters may be used for all Splunk @@ -117,7 +117,7 @@ Enterprise resources, including: `Standalone`, `LicenseMaster`, | licenseUrl | string | Full path or URL for a Splunk Enterprise license file | | licenseMasterRef | [ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectreference-v1-core) | Reference to a Splunk Operator managed `LicenseMaster` instance (via `name` and optionally `namespace`) to use for licensing | | clusterMasterRef | [ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectreference-v1-core) | Reference to a Splunk Operator managed `ClusterMaster` instance (via `name` and optionally `namespace`) to use for indexing | - +| 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 | ## Spark Resource Spec Parameters diff --git a/pkg/apis/enterprise/v1beta1/common_types.go b/pkg/apis/enterprise/v1beta1/common_types.go index d3f161eff..404f5f231 100644 --- a/pkg/apis/enterprise/v1beta1/common_types.go +++ b/pkg/apis/enterprise/v1beta1/common_types.go @@ -75,6 +75,9 @@ type CommonSplunkSpec struct { // Mock to differentiate between UTs and actual reconcile Mock bool `json:"Mock"` + + // ServiceAccount is the service account used by the pods deployed by the CRD + ServiceAccount string `json:"serviceAccount"` } // SmartStoreSpec defines Splunk indexes and remote storage volume configuration diff --git a/pkg/splunk/controller/serviceaccount.go b/pkg/splunk/controller/serviceaccount.go new file mode 100644 index 000000000..4bf11b968 --- /dev/null +++ b/pkg/splunk/controller/serviceaccount.go @@ -0,0 +1,57 @@ +// Copyright (c) 2018-2020 Splunk Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controller + +import ( + "context" + "reflect" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + + splcommon "github.com/splunk/splunk-operator/pkg/splunk/common" + splutil "github.com/splunk/splunk-operator/pkg/splunk/util" +) + +// ApplyServiceAccount creates or updates a Kubernetes serviceAccount +func ApplyServiceAccount(client splcommon.ControllerClient, serviceAccount *corev1.ServiceAccount) error { + namespacedName := types.NamespacedName{Namespace: serviceAccount.GetNamespace(), Name: serviceAccount.GetName()} + var current corev1.ServiceAccount + + err := client.Get(context.TODO(), namespacedName, ¤t) + if err == nil { + if !reflect.DeepEqual(serviceAccount, ¤t) { + current = *serviceAccount + err = splutil.UpdateResource(client, ¤t) + } + } else { + err = splutil.CreateResource(client, serviceAccount) + } + + return err +} + +// GetServiceAccount gets the serviceAccount resource in a given namespace +func GetServiceAccount(client splcommon.ControllerClient, namespacedName types.NamespacedName) (*corev1.ServiceAccount, error) { + scopedLog := log.WithName("GetServiceAccount").WithValues("serviceAccount", namespacedName.Name, + "namespace", namespacedName.Namespace) + var serviceAccount corev1.ServiceAccount + err := client.Get(context.TODO(), namespacedName, &serviceAccount) + if err != nil { + scopedLog.Info("ServiceAccount not found") + return nil, err + } + return &serviceAccount, nil +} diff --git a/pkg/splunk/controller/serviceaccount_test.go b/pkg/splunk/controller/serviceaccount_test.go new file mode 100644 index 000000000..30f8d37d4 --- /dev/null +++ b/pkg/splunk/controller/serviceaccount_test.go @@ -0,0 +1,73 @@ +// Copyright (c) 2018-2020 Splunk Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controller + +import ( + "testing" + + spltest "github.com/splunk/splunk-operator/pkg/splunk/test" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +func TestApplyServiceAccount(t *testing.T) { + funcCalls := []spltest.MockFuncCall{{MetaName: "*v1.ServiceAccount-test-defaults"}} + createCalls := map[string][]spltest.MockFuncCall{"Get": funcCalls, "Create": funcCalls} + updateCalls := map[string][]spltest.MockFuncCall{"Get": funcCalls, "Update": funcCalls} + current := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "defaults", + Namespace: "test", + }, + } + revised := current.DeepCopy() + revised.ResourceVersion = "dummy" + reconcile := func(c *spltest.MockClient, cr interface{}) error { + err := ApplyServiceAccount(c, cr.(*corev1.ServiceAccount)) + return err + } + spltest.ReconcileTester(t, "TestApplyServiceAccount", ¤t, revised, createCalls, updateCalls, reconcile, false) +} + +func TestGetServiceAccount(t *testing.T) { + current := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "defaults", + Namespace: "test", + }, + } + + client := spltest.NewMockClient() + namespacedName := types.NamespacedName{Namespace: current.GetNamespace(), Name: current.GetName()} + + // serviceAccount doesn't exist + _, err := GetServiceAccount(client, namespacedName) + if err == nil { + t.Errorf("Should return an error, when the serviceAccount doesn't exist") + } + + // Create serviceAccount + err = ApplyServiceAccount(client, ¤t) + if err != nil { + t.Errorf("Failed to create the serviceAccount. Error: %s", err.Error()) + } + + // Make sure serviceAccount exists + _, err = GetServiceAccount(client, namespacedName) + if err != nil { + t.Errorf("Should not return an error, when the serviceAccount exists") + } +} diff --git a/pkg/splunk/enterprise/clustermaster_test.go b/pkg/splunk/enterprise/clustermaster_test.go index ca5bc7830..0f40eb298 100644 --- a/pkg/splunk/enterprise/clustermaster_test.go +++ b/pkg/splunk/enterprise/clustermaster_test.go @@ -128,6 +128,16 @@ func TestGetClusterMasterStatefulSet(t *testing.T) { 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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"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_cluster_master"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_LICENSE_URI","value":"/mnt/splunk.lic"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"}],"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":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"securityContext":{"runAsUser":41812,"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}}`) + // Create a serviceaccount + current := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "defaults", + Namespace: "test", + }, + } + _ = splutil.CreateResource(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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-cluster-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"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_cluster_master"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_LICENSE_URI","value":"/mnt/splunk.lic"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"localhost"}],"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":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"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}}`) } func TestApplyClusterMasterWithSmartstore(t *testing.T) { diff --git a/pkg/splunk/enterprise/configuration.go b/pkg/splunk/enterprise/configuration.go index f660c67e9..3fb93edcc 100644 --- a/pkg/splunk/enterprise/configuration.go +++ b/pkg/splunk/enterprise/configuration.go @@ -416,6 +416,16 @@ func getSplunkStatefulSet(client splcommon.ControllerClient, cr splcommon.MetaOb } } + // add serviceaccount if configured + if spec.ServiceAccount != "" { + namespacedName := types.NamespacedName{Namespace: statefulSet.GetNamespace(), Name: spec.ServiceAccount} + _, err := splctrl.GetServiceAccount(client, namespacedName) + if err == nil { + // serviceAccount exists + statefulSet.Spec.Template.Spec.ServiceAccountName = spec.ServiceAccount + } + } + // append labels and annotations from parent splcommon.AppendParentMeta(statefulSet.Spec.Template.GetObjectMeta(), cr.GetObjectMeta()) diff --git a/pkg/splunk/enterprise/indexercluster_test.go b/pkg/splunk/enterprise/indexercluster_test.go index bfd9e681c..fef178609 100644 --- a/pkg/splunk/enterprise/indexercluster_test.go +++ b/pkg/splunk/enterprise/indexercluster_test.go @@ -1035,6 +1035,17 @@ func TestGetIndexerStatefulSet(t *testing.T) { 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-master1-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-master1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-indexer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"hec","containerPort":8088,"protocol":"TCP"},{"name":"splunkd","containerPort":8089,"protocol":"TCP"},{"name":"s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_indexer"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_INDEXER_URL","value":"splunk-stack1-indexer-0.splunk-stack1-indexer-headless.test.svc.cluster.local"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-master1-cluster-master-service"}],"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":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"securityContext":{"runAsUser":41812,"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-master1-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-master1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0}}`) + // Create a serviceaccount + current := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "defaults", + Namespace: "test", + }, + } + _ = splutil.CreateResource(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-master1-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-master1-indexer"},"annotations":{"traffic.sidecar.istio.io/excludeOutboundPorts":"8089,8191,9997,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-indexer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"hec","containerPort":8088,"protocol":"TCP"},{"name":"splunkd","containerPort":8089,"protocol":"TCP"},{"name":"s2s","containerPort":9997,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_indexer"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"name":"SPLUNK_INDEXER_URL","value":"splunk-stack1-indexer-0.splunk-stack1-indexer-headless.test.svc.cluster.local"},{"name":"SPLUNK_CLUSTER_MASTER_URL","value":"splunk-master1-cluster-master-service"}],"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":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"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-master1-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-master1-indexer"}},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"100Gi"}}},"status":{}}],"serviceName":"splunk-stack1-indexer-headless","podManagementPolicy":"Parallel","updateStrategy":{"type":"OnDelete"}},"status":{"replicas":0}}`) + cr.Spec.ClusterMasterRef.Namespace = "other" if err := validateIndexerClusterSpec(&cr); err == nil { t.Errorf("validateIndexerClusterSpec() error expected on multisite IndexerCluster referencing a cluster master located in a different namespace") diff --git a/pkg/splunk/enterprise/licensemaster_test.go b/pkg/splunk/enterprise/licensemaster_test.go index 2302a946c..33972935d 100644 --- a/pkg/splunk/enterprise/licensemaster_test.go +++ b/pkg/splunk/enterprise/licensemaster_test.go @@ -18,6 +18,7 @@ import ( "testing" "time" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -108,4 +109,15 @@ func TestGetLicenseMasterStatefulSet(t *testing.T) { // Allow installing apps via DefaultsURLApps for Licence Master 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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"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_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":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"securityContext":{"runAsUser":41812,"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}}`) + + // Create a serviceaccount + current := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "defaults", + Namespace: "test", + }, + } + _ = splutil.CreateResource(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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-license-master-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"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_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":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"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}}`) } diff --git a/pkg/splunk/enterprise/searchheadcluster_test.go b/pkg/splunk/enterprise/searchheadcluster_test.go index 65ab8b0f8..0aa0c9810 100644 --- a/pkg/splunk/enterprise/searchheadcluster_test.go +++ b/pkg/splunk/enterprise/searchheadcluster_test.go @@ -565,6 +565,17 @@ func TestGetSearchHeadStatefulSet(t *testing.T) { // 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-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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}},{"name":"mnt-splunk-jdk","emptyDir":{}},{"name":"mnt-splunk-spark","emptyDir":{}}],"initContainers":[{"name":"init","image":"splunk/spark","command":["bash","-c","cp -r /opt/jdk /mnt \u0026\u0026 cp -r /opt/spark /mnt"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"mnt-splunk-jdk","mountPath":"/mnt/jdk"},{"name":"mnt-splunk-spark","mountPath":"/mnt/spark"}],"imagePullPolicy":"IfNotPresent"}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"splunkd","containerPort":8089,"protocol":"TCP"},{"name":"dfsmaster","containerPort":9000,"protocol":"TCP"},{"name":"dfccontrol","containerPort":17000,"protocol":"TCP"},{"name":"datareceive","containerPort":19000,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"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-master-service.test2.svc.cluster.local"},{"name":"SPLUNK_ENABLE_DFS","value":"true"},{"name":"SPARK_MASTER_HOST","value":"splunk-stack1-spark-master-service"},{"name":"SPARK_MASTER_WEBUI_PORT","value":"8009"},{"name":"SPARK_HOME","value":"/mnt/splunk-spark"},{"name":"JAVA_HOME","value":"/mnt/splunk-jdk"},{"name":"SPLUNK_DFW_NUM_SLOTS_ENABLED","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-jdk","mountPath":"/mnt/splunk-jdk"},{"name":"mnt-splunk-spark","mountPath":"/mnt/splunk-spark"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"securityContext":{"runAsUser":41812,"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}}`) + + // Create a serviceaccount + current := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "defaults", + Namespace: "test", + }, + } + _ = splutil.CreateResource(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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-search-head-secret-v1","defaultMode":420}},{"name":"mnt-splunk-jdk","emptyDir":{}},{"name":"mnt-splunk-spark","emptyDir":{}}],"initContainers":[{"name":"init","image":"splunk/spark","command":["bash","-c","cp -r /opt/jdk /mnt \u0026\u0026 cp -r /opt/spark /mnt"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"mnt-splunk-jdk","mountPath":"/mnt/jdk"},{"name":"mnt-splunk-spark","mountPath":"/mnt/spark"}],"imagePullPolicy":"IfNotPresent"}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"splunkd","containerPort":8089,"protocol":"TCP"},{"name":"dfsmaster","containerPort":9000,"protocol":"TCP"},{"name":"dfccontrol","containerPort":17000,"protocol":"TCP"},{"name":"datareceive","containerPort":19000,"protocol":"TCP"},{"name":"user-defined","containerPort":32000,"protocol":"UDP"}],"env":[{"name":"SPLUNK_HOME","value":"/opt/splunk"},{"name":"SPLUNK_START_ARGS","value":"--accept-license"},{"name":"SPLUNK_DEFAULTS_URL","value":"/mnt/splunk-secrets/default.yml"},{"name":"SPLUNK_HOME_OWNERSHIP_ENFORCEMENT","value":"false"},{"name":"SPLUNK_ROLE","value":"splunk_search_head"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"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-master-service.test2.svc.cluster.local"},{"name":"SPLUNK_ENABLE_DFS","value":"true"},{"name":"SPARK_MASTER_HOST","value":"splunk-stack1-spark-master-service"},{"name":"SPARK_MASTER_WEBUI_PORT","value":"8009"},{"name":"SPARK_HOME","value":"/mnt/splunk-spark"},{"name":"JAVA_HOME","value":"/mnt/splunk-jdk"},{"name":"SPLUNK_DFW_NUM_SLOTS_ENABLED","value":"true"}],"resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"volumeMounts":[{"name":"pvc-etc","mountPath":"/opt/splunk/etc"},{"name":"pvc-var","mountPath":"/opt/splunk/var"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-jdk","mountPath":"/mnt/splunk-jdk"},{"name":"mnt-splunk-spark","mountPath":"/mnt/splunk-spark"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"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}}`) } func TestGetDeployerStatefulSet(t *testing.T) { @@ -598,4 +609,14 @@ func TestGetDeployerStatefulSet(t *testing.T) { 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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-deployer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"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_deployer"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"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"}],"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":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"securityContext":{"runAsUser":41812,"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}}`) + // Create a serviceaccount + current := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "defaults", + Namespace: "test", + }, + } + _ = splutil.CreateResource(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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000"}},"spec":{"volumes":[{"name":"mnt-splunk-secrets","secret":{"secretName":"splunk-stack1-deployer-secret-v1","defaultMode":420}}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"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_deployer"},{"name":"SPLUNK_DECLARATIVE_ADMIN_PASSWORD","value":"true"},{"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"}],"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":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"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}}`) } diff --git a/pkg/splunk/enterprise/standalone_test.go b/pkg/splunk/enterprise/standalone_test.go index ba2a4e57d..d11a0aebe 100644 --- a/pkg/splunk/enterprise/standalone_test.go +++ b/pkg/splunk/enterprise/standalone_test.go @@ -219,6 +219,17 @@ func TestGetStandaloneStatefulSet(t *testing.T) { 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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"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}},{"name":"mnt-splunk-jdk","emptyDir":{}},{"name":"mnt-splunk-spark","emptyDir":{}}],"initContainers":[{"name":"init","image":"splunk/spark","command":["bash","-c","cp -r /opt/jdk /mnt \u0026\u0026 cp -r /opt/spark /mnt"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"mnt-splunk-jdk","mountPath":"/mnt/jdk"},{"name":"mnt-splunk-spark","mountPath":"/mnt/spark"}],"imagePullPolicy":"IfNotPresent"}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"hec","containerPort":8088,"protocol":"TCP"},{"name":"splunkd","containerPort":8089,"protocol":"TCP"},{"name":"dfsmaster","containerPort":9000,"protocol":"TCP"},{"name":"s2s","containerPort":9997,"protocol":"TCP"},{"name":"dfccontrol","containerPort":17000,"protocol":"TCP"},{"name":"datareceive","containerPort":19000,"protocol":"TCP"}],"env":[{"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_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-master-service"},{"name":"SPLUNK_ENABLE_DFS","value":"true"},{"name":"SPARK_MASTER_HOST","value":"splunk-stack1-spark-master-service"},{"name":"SPARK_MASTER_WEBUI_PORT","value":"8009"},{"name":"SPARK_HOME","value":"/mnt/splunk-spark"},{"name":"JAVA_HOME","value":"/mnt/splunk-jdk"},{"name":"SPLUNK_DFW_NUM_SLOTS_ENABLED","value":"false"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"},{"name":"mnt-splunk-jdk","mountPath":"/mnt/splunk-jdk"},{"name":"mnt-splunk-spark","mountPath":"/mnt/splunk-spark"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"securityContext":{"runAsUser":41812,"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}}`) + + // Create a serviceaccount + current := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "defaults", + Namespace: "test", + }, + } + _ = splutil.CreateResource(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,7777,9000,17000,17500,19000","traffic.sidecar.istio.io/includeInboundPorts":"8000,8088"}},"spec":{"volumes":[{"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}},{"name":"mnt-splunk-jdk","emptyDir":{}},{"name":"mnt-splunk-spark","emptyDir":{}}],"initContainers":[{"name":"init","image":"splunk/spark","command":["bash","-c","cp -r /opt/jdk /mnt \u0026\u0026 cp -r /opt/spark /mnt"],"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"250m","memory":"128Mi"}},"volumeMounts":[{"name":"mnt-splunk-jdk","mountPath":"/mnt/jdk"},{"name":"mnt-splunk-spark","mountPath":"/mnt/spark"}],"imagePullPolicy":"IfNotPresent"}],"containers":[{"name":"splunk","image":"splunk/splunk","ports":[{"name":"splunkweb","containerPort":8000,"protocol":"TCP"},{"name":"hec","containerPort":8088,"protocol":"TCP"},{"name":"splunkd","containerPort":8089,"protocol":"TCP"},{"name":"dfsmaster","containerPort":9000,"protocol":"TCP"},{"name":"s2s","containerPort":9997,"protocol":"TCP"},{"name":"dfccontrol","containerPort":17000,"protocol":"TCP"},{"name":"datareceive","containerPort":19000,"protocol":"TCP"}],"env":[{"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_CLUSTER_MASTER_URL","value":"splunk-stack2-cluster-master-service"},{"name":"SPLUNK_ENABLE_DFS","value":"true"},{"name":"SPARK_MASTER_HOST","value":"splunk-stack1-spark-master-service"},{"name":"SPARK_MASTER_WEBUI_PORT","value":"8009"},{"name":"SPARK_HOME","value":"/mnt/splunk-spark"},{"name":"JAVA_HOME","value":"/mnt/splunk-jdk"},{"name":"SPLUNK_DFW_NUM_SLOTS_ENABLED","value":"false"}],"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":"defaults","mountPath":"/mnt/defaults"},{"name":"mnt-splunk-secrets","mountPath":"/mnt/splunk-secrets"},{"name":"mnt-splunk-defaults","mountPath":"/mnt/splunk-defaults"},{"name":"mnt-splunk-jdk","mountPath":"/mnt/splunk-jdk"},{"name":"mnt-splunk-spark","mountPath":"/mnt/splunk-spark"}],"livenessProbe":{"exec":{"command":["/sbin/checkstate.sh"]},"initialDelaySeconds":300,"timeoutSeconds":30,"periodSeconds":30},"readinessProbe":{"exec":{"command":["/bin/grep","started","/opt/container_artifact/splunk-container.state"]},"initialDelaySeconds":10,"timeoutSeconds":5,"periodSeconds":5},"imagePullPolicy":"IfNotPresent"}],"serviceAccountName":"defaults","securityContext":{"runAsUser":41812,"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}}`) } func TestApplyStandaloneSmartstoreKeyChangeDetection(t *testing.T) { diff --git a/pkg/splunk/test/controller.go b/pkg/splunk/test/controller.go index 099177361..99b5149b0 100644 --- a/pkg/splunk/test/controller.go +++ b/pkg/splunk/test/controller.go @@ -85,6 +85,8 @@ func coreObjectCopier(dst, src *runtime.Object) bool { *dstP.(*corev1.Service) = *srcP.(*corev1.Service) case *corev1.Pod: *dstP.(*corev1.Pod) = *srcP.(*corev1.Pod) + case *corev1.ServiceAccount: + *dstP.(*corev1.ServiceAccount) = *srcP.(*corev1.ServiceAccount) default: return false } From c41e0f5c327dd08d894d8dde4ec5b7e1c0019911 Mon Sep 17 00:00:00 2001 From: akondur Date: Thu, 14 Jan 2021 11:08:23 -0800 Subject: [PATCH 2/6] Additional ut check for serviceaccount --- pkg/splunk/controller/serviceaccount_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/splunk/controller/serviceaccount_test.go b/pkg/splunk/controller/serviceaccount_test.go index 30f8d37d4..7f837b2fd 100644 --- a/pkg/splunk/controller/serviceaccount_test.go +++ b/pkg/splunk/controller/serviceaccount_test.go @@ -66,8 +66,11 @@ func TestGetServiceAccount(t *testing.T) { } // Make sure serviceAccount exists - _, err = GetServiceAccount(client, namespacedName) + got, err := GetServiceAccount(client, namespacedName) if err != nil { + if got.GetName() != current.GetName() { + t.Errorf("Incorrect service account retrieved got %s want %s", got.GetName(), current.GetName()) + } t.Errorf("Should not return an error, when the serviceAccount exists") } } From 90b391b4107fe857b8952237c95f62d1dd0a79bb Mon Sep 17 00:00:00 2001 From: akondur Date: Thu, 14 Jan 2021 18:12:56 -0800 Subject: [PATCH 3/6] Additional ut for update scenario --- pkg/splunk/controller/serviceaccount_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pkg/splunk/controller/serviceaccount_test.go b/pkg/splunk/controller/serviceaccount_test.go index 7f837b2fd..f60834f25 100644 --- a/pkg/splunk/controller/serviceaccount_test.go +++ b/pkg/splunk/controller/serviceaccount_test.go @@ -73,4 +73,22 @@ func TestGetServiceAccount(t *testing.T) { } t.Errorf("Should not return an error, when the serviceAccount exists") } + + var dummySaName string = "dummy_sa" + + current.Name = dummySaName + // Update serviceAccount + err = ApplyServiceAccount(client, ¤t) + if err != nil { + t.Errorf("Failed to create the serviceAccount. Error: %s", err.Error()) + } + + // Make sure serviceAccount is updated + got, err = GetServiceAccount(client, namespacedName) + if err != nil { + if got.GetName() != dummySaName { + t.Errorf("Incorrect service account retrieved got %s want %s", got.GetName(), current.GetName()) + } + t.Errorf("Should not return an error, when the serviceAccount exists") + } } From afba86e89a59cff213f63846952031dbcd41c36c Mon Sep 17 00:00:00 2001 From: akondur Date: Fri, 15 Jan 2021 13:57:11 -0800 Subject: [PATCH 4/6] Addressing review comments --- deploy/crds/enterprise.splunk.com_clustermasters_crd.yaml | 3 ++- deploy/crds/enterprise.splunk.com_indexerclusters_crd.yaml | 3 ++- deploy/crds/enterprise.splunk.com_licensemasters_crd.yaml | 3 ++- deploy/crds/enterprise.splunk.com_searchheadclusters_crd.yaml | 3 ++- deploy/crds/enterprise.splunk.com_standalones_crd.yaml | 3 ++- .../0.2.1/enterprise.splunk.com_clustermasters_crd.yaml | 3 ++- .../0.2.1/enterprise.splunk.com_indexerclusters_crd.yaml | 3 ++- .../0.2.1/enterprise.splunk.com_licensemasters_crd.yaml | 3 ++- .../0.2.1/enterprise.splunk.com_searchheadclusters_crd.yaml | 3 ++- .../splunk/0.2.1/enterprise.splunk.com_standalones_crd.yaml | 3 ++- pkg/apis/enterprise/v1beta1/common_types.go | 4 +++- pkg/splunk/controller/serviceaccount.go | 4 ++++ 12 files changed, 27 insertions(+), 11 deletions(-) diff --git a/deploy/crds/enterprise.splunk.com_clustermasters_crd.yaml b/deploy/crds/enterprise.splunk.com_clustermasters_crd.yaml index d67a2a231..c194ad2ed 100644 --- a/deploy/crds/enterprise.splunk.com_clustermasters_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_clustermasters_crd.yaml @@ -754,7 +754,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/deploy/crds/enterprise.splunk.com_indexerclusters_crd.yaml b/deploy/crds/enterprise.splunk.com_indexerclusters_crd.yaml index 39ef02106..d2e5189f4 100644 --- a/deploy/crds/enterprise.splunk.com_indexerclusters_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_indexerclusters_crd.yaml @@ -781,7 +781,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/deploy/crds/enterprise.splunk.com_licensemasters_crd.yaml b/deploy/crds/enterprise.splunk.com_licensemasters_crd.yaml index 8715c4afc..b2fe9ab56 100644 --- a/deploy/crds/enterprise.splunk.com_licensemasters_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_licensemasters_crd.yaml @@ -759,7 +759,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/deploy/crds/enterprise.splunk.com_searchheadclusters_crd.yaml b/deploy/crds/enterprise.splunk.com_searchheadclusters_crd.yaml index 6b6ce4925..11ffcea16 100644 --- a/deploy/crds/enterprise.splunk.com_searchheadclusters_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_searchheadclusters_crd.yaml @@ -781,7 +781,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/deploy/crds/enterprise.splunk.com_standalones_crd.yaml b/deploy/crds/enterprise.splunk.com_standalones_crd.yaml index 0c2273a5c..ec058bd40 100644 --- a/deploy/crds/enterprise.splunk.com_standalones_crd.yaml +++ b/deploy/crds/enterprise.splunk.com_standalones_crd.yaml @@ -775,7 +775,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_clustermasters_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_clustermasters_crd.yaml index d67a2a231..c194ad2ed 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_clustermasters_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_clustermasters_crd.yaml @@ -754,7 +754,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_indexerclusters_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_indexerclusters_crd.yaml index 39ef02106..d2e5189f4 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_indexerclusters_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_indexerclusters_crd.yaml @@ -781,7 +781,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_licensemasters_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_licensemasters_crd.yaml index 8715c4afc..b2fe9ab56 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_licensemasters_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_licensemasters_crd.yaml @@ -759,7 +759,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_searchheadclusters_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_searchheadclusters_crd.yaml index 6b6ce4925..11ffcea16 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_searchheadclusters_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_searchheadclusters_crd.yaml @@ -781,7 +781,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_standalones_crd.yaml b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_standalones_crd.yaml index 0c2273a5c..ec058bd40 100644 --- a/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_standalones_crd.yaml +++ b/deploy/olm-catalog/splunk/0.2.1/enterprise.splunk.com_standalones_crd.yaml @@ -775,7 +775,8 @@ spec: type: string serviceAccount: description: ServiceAccount is the service account used by the pods - deployed by the CRD + deployed by the CRD. If not specified uses the default serviceAccount + for the namespace as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server type: string serviceTemplate: description: ServiceTemplate is a template used to create Kubernetes diff --git a/pkg/apis/enterprise/v1beta1/common_types.go b/pkg/apis/enterprise/v1beta1/common_types.go index 5549b5d35..b82b4d69b 100644 --- a/pkg/apis/enterprise/v1beta1/common_types.go +++ b/pkg/apis/enterprise/v1beta1/common_types.go @@ -70,7 +70,9 @@ type CommonSplunkSpec struct { // Mock to differentiate between UTs and actual reconcile Mock bool `json:"Mock"` - // ServiceAccount is the service account used by the pods deployed by the CRD + // ServiceAccount is the service account used by the pods deployed by the CRD. + // If not specified uses the default serviceAccount for the namespace as per + // https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server ServiceAccount string `json:"serviceAccount"` } diff --git a/pkg/splunk/controller/serviceaccount.go b/pkg/splunk/controller/serviceaccount.go index 4bf11b968..e3790c08d 100644 --- a/pkg/splunk/controller/serviceaccount.go +++ b/pkg/splunk/controller/serviceaccount.go @@ -27,12 +27,16 @@ import ( // ApplyServiceAccount creates or updates a Kubernetes serviceAccount func ApplyServiceAccount(client splcommon.ControllerClient, serviceAccount *corev1.ServiceAccount) error { + scopedLog := log.WithName("ApplyServiceAccount").WithValues("serviceAccount", serviceAccount.GetName(), + "namespace", serviceAccount.GetNamespace()) + namespacedName := types.NamespacedName{Namespace: serviceAccount.GetNamespace(), Name: serviceAccount.GetName()} var current corev1.ServiceAccount err := client.Get(context.TODO(), namespacedName, ¤t) if err == nil { if !reflect.DeepEqual(serviceAccount, ¤t) { + scopedLog.Info("Updating service account") current = *serviceAccount err = splutil.UpdateResource(client, ¤t) } From f347b9013870a3e9869635d8be091e1450b85dcd Mon Sep 17 00:00:00 2001 From: akondur Date: Wed, 20 Jan 2021 13:34:44 -0800 Subject: [PATCH 5/6] Give access to the resource serviceaccount --- deploy/role.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/role.yaml b/deploy/role.yaml index 04fc10938..51dd9440e 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -14,6 +14,7 @@ rules: - secrets - pods - pods/exec + - serviceaccounts verbs: - create - delete From 9cc89e1c083089cc4bd9dd105eb37dfe2375d086 Mon Sep 17 00:00:00 2001 From: akondur Date: Wed, 20 Jan 2021 13:40:08 -0800 Subject: [PATCH 6/6] Changed logging for GetServiceAccount --- pkg/splunk/controller/serviceaccount.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/splunk/controller/serviceaccount.go b/pkg/splunk/controller/serviceaccount.go index e3790c08d..516605b87 100644 --- a/pkg/splunk/controller/serviceaccount.go +++ b/pkg/splunk/controller/serviceaccount.go @@ -49,11 +49,11 @@ func ApplyServiceAccount(client splcommon.ControllerClient, serviceAccount *core // GetServiceAccount gets the serviceAccount resource in a given namespace func GetServiceAccount(client splcommon.ControllerClient, namespacedName types.NamespacedName) (*corev1.ServiceAccount, error) { - scopedLog := log.WithName("GetServiceAccount").WithValues("serviceAccount", namespacedName.Name, - "namespace", namespacedName.Namespace) var serviceAccount corev1.ServiceAccount err := client.Get(context.TODO(), namespacedName, &serviceAccount) if err != nil { + scopedLog := log.WithName("GetServiceAccount").WithValues("serviceAccount", namespacedName.Name, + "namespace", namespacedName.Namespace, "error", err) scopedLog.Info("ServiceAccount not found") return nil, err }