From 2b79aecded3628594a967de32da275865125ac45 Mon Sep 17 00:00:00 2001 From: Marc Navarro Sonnenfeld Date: Tue, 12 Mar 2024 16:09:19 +0100 Subject: [PATCH] Support serviceAccountName configuration overwrite --- api/v1/kubegres_types.go | 29 +-- .../kubegres.reactive-tech.io_kubegres.yaml | 2 + internal/controller/ctx/KubegresContext.go | 6 +- .../ctx/resources/ResourcesContext.go | 3 + .../ServiceAccountNameSpecEnforcer.go | 63 ++++++ .../template/ResourcesCreatorFromTemplate.go | 7 +- .../spec/template/yaml/Templates.go | 10 +- .../test/resourceConfigs/ConfigForTest.go | 3 + internal/test/resourceConfigs/LoadTestYaml.go | 9 +- .../test/resourceConfigs/serviceAccount.yaml | 5 + internal/test/spec_serviceAccountName_test.go | 208 ++++++++++++++++++ internal/test/util/TestResourceCreator.go | 25 ++- 12 files changed, 343 insertions(+), 27 deletions(-) create mode 100644 internal/controller/spec/enforcer/statefulset_spec/ServiceAccountNameSpecEnforcer.go create mode 100644 internal/test/resourceConfigs/serviceAccount.yaml create mode 100644 internal/test/spec_serviceAccountName_test.go diff --git a/api/v1/kubegres_types.go b/api/v1/kubegres_types.go index 5533e35..c517453 100644 --- a/api/v1/kubegres_types.go +++ b/api/v1/kubegres_types.go @@ -62,20 +62,21 @@ type Probe struct { } type KubegresSpec struct { - Replicas *int32 `json:"replicas,omitempty"` - Image string `json:"image,omitempty"` - Port int32 `json:"port,omitempty"` - ImagePullSecrets []v1.LocalObjectReference `json:"imagePullSecrets,omitempty"` - CustomConfig string `json:"customConfig,omitempty"` - Database KubegresDatabase `json:"database,omitempty"` - Failover KubegresFailover `json:"failover,omitempty"` - Backup KubegresBackUp `json:"backup,omitempty"` - Env []v1.EnvVar `json:"env,omitempty"` - Scheduler KubegresScheduler `json:"scheduler,omitempty"` - Resources v1.ResourceRequirements `json:"resources,omitempty"` - Volume Volume `json:"volume,omitempty"` - SecurityContext *v1.PodSecurityContext `json:"securityContext,omitempty"` - Probe Probe `json:"probe,omitempty"` + Replicas *int32 `json:"replicas,omitempty"` + Image string `json:"image,omitempty"` + Port int32 `json:"port,omitempty"` + ImagePullSecrets []v1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + CustomConfig string `json:"customConfig,omitempty"` + Database KubegresDatabase `json:"database,omitempty"` + Failover KubegresFailover `json:"failover,omitempty"` + Backup KubegresBackUp `json:"backup,omitempty"` + Env []v1.EnvVar `json:"env,omitempty"` + Scheduler KubegresScheduler `json:"scheduler,omitempty"` + Resources v1.ResourceRequirements `json:"resources,omitempty"` + Volume Volume `json:"volume,omitempty"` + SecurityContext *v1.PodSecurityContext `json:"securityContext,omitempty"` + Probe Probe `json:"probe,omitempty"` + ServiceAccountName string `json:"serviceAccountName,omitempty"` } // ----------------------- STATUS ----------------------------------------- diff --git a/config/crd/bases/kubegres.reactive-tech.io_kubegres.yaml b/config/crd/bases/kubegres.reactive-tech.io_kubegres.yaml index 2c43a7f..4b76f05 100644 --- a/config/crd/bases/kubegres.reactive-tech.io_kubegres.yaml +++ b/config/crd/bases/kubegres.reactive-tech.io_kubegres.yaml @@ -1619,6 +1619,8 @@ spec: type: string type: object type: object + serviceAccountName: + type: string volume: properties: volumeClaimTemplates: diff --git a/internal/controller/ctx/KubegresContext.go b/internal/controller/ctx/KubegresContext.go index f420606..ef22cae 100644 --- a/internal/controller/ctx/KubegresContext.go +++ b/internal/controller/ctx/KubegresContext.go @@ -22,12 +22,13 @@ package ctx import ( "context" + "strconv" + "strings" + "reactive-tech.io/kubegres/api/v1" "reactive-tech.io/kubegres/internal/controller/ctx/log" "reactive-tech.io/kubegres/internal/controller/ctx/status" "sigs.k8s.io/controller-runtime/pkg/client" - "strconv" - "strings" ) type KubegresContext struct { @@ -48,6 +49,7 @@ const ( BaseConfigMapName = "base-kubegres-config" CronJobNamePrefix = "backup-" DefaultContainerPortNumber = 5432 + DefaultPodServiceAccountName = "default" DefaultDatabaseVolumeMount = "/var/lib/postgresql/data" DefaultDatabaseFolder = "pgdata" EnvVarNamePgData = "PGDATA" diff --git a/internal/controller/ctx/resources/ResourcesContext.go b/internal/controller/ctx/resources/ResourcesContext.go index 916b408..47e5332 100644 --- a/internal/controller/ctx/resources/ResourcesContext.go +++ b/internal/controller/ctx/resources/ResourcesContext.go @@ -22,6 +22,7 @@ package resources import ( "context" + ctx2 "reactive-tech.io/kubegres/internal/controller/ctx" "reactive-tech.io/kubegres/internal/controller/ctx/log" "reactive-tech.io/kubegres/internal/controller/ctx/status" @@ -166,6 +167,7 @@ func addStatefulSetSpecEnforcers(rc *ResourcesContext) { securityContextSpecEnforcer := statefulset_spec2.CreateSecurityContextSpecEnforcer(rc.KubegresContext) livenessProbeSpecEnforcer := statefulset_spec2.CreateLivenessProbeSpecEnforcer(rc.KubegresContext) readinessProbeSpecEnforcer := statefulset_spec2.CreateReadinessProbeSpecEnforcer(rc.KubegresContext) + serviAccountNameSpecEnforcer := statefulset_spec2.CreateServiceAccountNameSpecEnforcer(rc.KubegresContext) rc.StatefulSetsSpecsEnforcer = statefulset_spec2.CreateStatefulSetsSpecsEnforcer(rc.KubegresContext) rc.StatefulSetsSpecsEnforcer.AddSpecEnforcer(&imageSpecEnforcer) @@ -179,6 +181,7 @@ func addStatefulSetSpecEnforcers(rc *ResourcesContext) { rc.StatefulSetsSpecsEnforcer.AddSpecEnforcer(&securityContextSpecEnforcer) rc.StatefulSetsSpecsEnforcer.AddSpecEnforcer(&livenessProbeSpecEnforcer) rc.StatefulSetsSpecsEnforcer.AddSpecEnforcer(&readinessProbeSpecEnforcer) + rc.StatefulSetsSpecsEnforcer.AddSpecEnforcer(&serviAccountNameSpecEnforcer) rc.AllStatefulSetsSpecEnforcer = statefulset_spec2.CreateAllStatefulSetsSpecEnforcer(rc.KubegresContext, rc.ResourcesStates, rc.BlockingOperation, rc.StatefulSetsSpecsEnforcer) } diff --git a/internal/controller/spec/enforcer/statefulset_spec/ServiceAccountNameSpecEnforcer.go b/internal/controller/spec/enforcer/statefulset_spec/ServiceAccountNameSpecEnforcer.go new file mode 100644 index 0000000..8960403 --- /dev/null +++ b/internal/controller/spec/enforcer/statefulset_spec/ServiceAccountNameSpecEnforcer.go @@ -0,0 +1,63 @@ +/* +Copyright 2023 Reactive Tech Limited. +"Reactive Tech Limited" is a company located in England, United Kingdom. +https://www.reactive-tech.io + +Lead Developer: Alex Arica + +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 statefulset_spec + +import ( + apps "k8s.io/api/apps/v1" + "reactive-tech.io/kubegres/internal/controller/ctx" +) + +type ServiceAccountNameSpecEnforcer struct { + kubegresContext ctx.KubegresContext +} + +func CreateServiceAccountNameSpecEnforcer(kubegresContext ctx.KubegresContext) ServiceAccountNameSpecEnforcer { + return ServiceAccountNameSpecEnforcer{kubegresContext: kubegresContext} +} + +func (r *ServiceAccountNameSpecEnforcer) GetSpecName() string { + return "ServiceAccountName" +} + +func (r *ServiceAccountNameSpecEnforcer) CheckForSpecDifference(statefulSet *apps.StatefulSet) StatefulSetSpecDifference { + + current := statefulSet.Spec.Template.Spec.ServiceAccountName + expected := r.kubegresContext.Kubegres.Spec.ServiceAccountName + + if current != expected { + return StatefulSetSpecDifference{ + SpecName: r.GetSpecName(), + Current: current, + Expected: expected, + } + } + + return StatefulSetSpecDifference{} +} + +func (r *ServiceAccountNameSpecEnforcer) EnforceSpec(statefulSet *apps.StatefulSet) (wasSpecUpdated bool, err error) { + statefulSet.Spec.Template.Spec.ServiceAccountName = r.kubegresContext.Kubegres.Spec.ServiceAccountName + return true, nil +} + +func (r *ServiceAccountNameSpecEnforcer) OnSpecEnforcedSuccessfully(_ *apps.StatefulSet) error { + return nil +} diff --git a/internal/controller/spec/template/ResourcesCreatorFromTemplate.go b/internal/controller/spec/template/ResourcesCreatorFromTemplate.go index 2d8cae8..f78609e 100644 --- a/internal/controller/spec/template/ResourcesCreatorFromTemplate.go +++ b/internal/controller/spec/template/ResourcesCreatorFromTemplate.go @@ -21,9 +21,10 @@ limitations under the License. package template import ( - "reactive-tech.io/kubegres/internal/controller/ctx" "strconv" + "reactive-tech.io/kubegres/internal/controller/ctx" + apps "k8s.io/api/apps/v1" batch "k8s.io/api/batch/v1" core "k8s.io/api/core/v1" @@ -264,6 +265,10 @@ func (r *ResourcesCreatorFromTemplate) initStatefulSet( if postgresSpec.Probe.ReadinessProbe != nil { statefulSetTemplate.Spec.Template.Spec.Containers[0].ReadinessProbe = postgresSpec.Probe.ReadinessProbe } + + if postgresSpec.ServiceAccountName != "" { + statefulSetTemplate.Spec.Template.Spec.ServiceAccountName = postgresSpec.ServiceAccountName + } } // Extract annotations set in Kubegres YAML by diff --git a/internal/controller/spec/template/yaml/Templates.go b/internal/controller/spec/template/yaml/Templates.go index 9889f56..1bc7e47 100644 --- a/internal/controller/spec/template/yaml/Templates.go +++ b/internal/controller/spec/template/yaml/Templates.go @@ -152,12 +152,10 @@ data: #echo "$dt - Running: psql -v ON_ERROR_STOP=1 --username $POSTGRES_USER --dbname $POSTGRES_DB ..."; #psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL - #CREATE DATABASE $customDatabaseName; - #\connect $customDatabaseName; - #CREATE USER $customUserName WITH PASSWORD '$POSTGRES_MYAPP_PASSWORD'; - #GRANT SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON ALL TABLES IN SCHEMA public TO $customUserName; - #GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public TO $customUserName; - #GRANT USAGE, CREATE ON SCHEMA public TO $customUserName; + #CREATE USER $customUserName WITH PASSWORD '$POSTGRES_MYAPP_PASSWORD'; + #CREATE DATABASE $customDatabaseName; + #\connect $customDatabaseName; + #GRANT ALL ON SCHEMA public TO $customUserName; #EOSQL #echo "$dt - Init script is completed"; diff --git a/internal/test/resourceConfigs/ConfigForTest.go b/internal/test/resourceConfigs/ConfigForTest.go index 768eb8a..19a1600 100644 --- a/internal/test/resourceConfigs/ConfigForTest.go +++ b/internal/test/resourceConfigs/ConfigForTest.go @@ -40,6 +40,9 @@ const ( SecretYamlFile = "resourceConfigs/secret.yaml" SecretResourceName = "my-kubegres-secret" + ServiceAccountYamlFile = "resourceConfigs/serviceAccount.yaml" + ServiceAccountResourceName = "my-kubegres" + ServiceToSqlQueryPrimaryDbYamlFile = "resourceConfigs/primaryService.yaml" ServiceToSqlQueryPrimaryDbResourceName = "test-kubegres-primary" ServiceToSqlQueryPrimaryDbNodePort = 30007 diff --git a/internal/test/resourceConfigs/LoadTestYaml.go b/internal/test/resourceConfigs/LoadTestYaml.go index 1a2ba1b..b66bff3 100644 --- a/internal/test/resourceConfigs/LoadTestYaml.go +++ b/internal/test/resourceConfigs/LoadTestYaml.go @@ -22,10 +22,11 @@ package resourceConfigs import ( "io/ioutil" + "log" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/scheme" - "log" kubegresv1 "reactive-tech.io/kubegres/api/v1" ) @@ -53,6 +54,12 @@ func LoadSecretYaml() v1.Secret { return *obj.(*v1.Secret) } +func LoadServiceAccountYaml() v1.ServiceAccount { + fileContents := getFileContents(ServiceAccountYamlFile) + obj := decodeYaml(fileContents) + return *obj.(*v1.ServiceAccount) +} + func LoadYamlServiceToSqlQueryPrimaryDb() v1.Service { fileContents := getFileContents(ServiceToSqlQueryPrimaryDbYamlFile) obj := decodeYaml(fileContents) diff --git a/internal/test/resourceConfigs/serviceAccount.yaml b/internal/test/resourceConfigs/serviceAccount.yaml new file mode 100644 index 0000000..373a7c5 --- /dev/null +++ b/internal/test/resourceConfigs/serviceAccount.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: my-kubegres + namespace: default \ No newline at end of file diff --git a/internal/test/spec_serviceAccountName_test.go b/internal/test/spec_serviceAccountName_test.go new file mode 100644 index 0000000..17c70c2 --- /dev/null +++ b/internal/test/spec_serviceAccountName_test.go @@ -0,0 +1,208 @@ +/* +Copyright 2023 Reactive Tech Limited. +"Reactive Tech Limited" is a company located in England, United Kingdom. +https://www.reactive-tech.io + +Lead Developer: Alex Arica + +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 test + +import ( + "log" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + apierrors "k8s.io/apimachinery/pkg/api/errors" + postgresv1 "reactive-tech.io/kubegres/api/v1" + "reactive-tech.io/kubegres/internal/controller/ctx" + "reactive-tech.io/kubegres/internal/test/resourceConfigs" + "reactive-tech.io/kubegres/internal/test/util" + "reactive-tech.io/kubegres/internal/test/util/testcases" +) + +var _ = Describe("Setting Kubegres spec 'serviceAccountName'", func() { + + var test = SpecServiceAccountNameTest{} + + BeforeEach(func() { + namespace := resourceConfigs.DefaultNamespace + test.resourceRetriever = util.CreateTestResourceRetriever(k8sClientTest, namespace) + test.resourceCreator = util.CreateTestResourceCreator(k8sClientTest, test.resourceRetriever, namespace) + test.dbQueryTestCases = testcases.InitDbQueryTestCases(test.resourceCreator, resourceConfigs.KubegresResourceName) + }) + + AfterEach(func() { + if !test.keepCreatedResourcesForNextTest { + test.resourceCreator.DeleteAllTestResources() + } else { + test.keepCreatedResourcesForNextTest = false + } + }) + + Context("GIVEN new Kubegres is created without spec 'serviceAccountName' and with spec 'replica' set to 3", func() { + + It("THEN 1 primary and 2 replica should be created with serviceAccountName 'default' and a normal event should be logged", func() { + + log.Print("START OF: Test 'GIVEN new Kubegres is created without spec 'serviceAccountName' and with spec 'replica' set to 3'") + + test.givenNewKubegresSpecIsSetTo("", 3) + + test.whenKubegresIsCreated() + + test.thenPodsStatesShouldBe(ctx.DefaultPodServiceAccountName, 1, 2) + + test.thenDeployedKubegresSpecShouldBeSetTo("") + + test.dbQueryTestCases.ThenWeCanSqlQueryPrimaryDb() + test.dbQueryTestCases.ThenWeCanSqlQueryReplicaDb() + + log.Print("END OF: Test 'GIVEN new Kubegres is created without spec 'serviceAccountName' and with spec 'replica' set to 3'") + }) + }) + + Context("GIVEN new Kubegres is created with spec 'serviceAccountName' set to 'my-kubegres' and spec 'replica' set to 3 and later 'serviceAccountName' is updated to 'changed-kubegres'", func() { + + It("GIVEN new Kubegres is created with spec 'serviceAccountName' set to 'my-kubegres' and spec 'replica' set to 3 THEN 1 primary and 2 replica should be created with spec 'serviceAccountName' set to 'kubegres", func() { + + log.Print("START OF: Test 'GIVEN new Kubegres is created with spec 'serviceAccountName' set to 'my-kubegres' and spec 'replica' set to 3") + + test.whenServiceAccountIsCreated("my-kubegres") + + test.givenNewKubegresSpecIsSetTo("my-kubegres", 3) + + test.whenKubegresIsCreated() + + test.thenPodsStatesShouldBe("my-kubegres", 1, 2) + + test.thenDeployedKubegresSpecShouldBeSetTo("my-kubegres") + + test.dbQueryTestCases.ThenWeCanSqlQueryPrimaryDb() + test.dbQueryTestCases.ThenWeCanSqlQueryReplicaDb() + + test.keepCreatedResourcesForNextTest = true + + log.Print("END OF: Test 'GIVEN new Kubegres is created with spec 'serviceAccountName' set to 'my-kubegres' and spec 'replica' set to 3'") + }) + + It("GIVEN existing Kubegres is updated with spec 'serviceAccountName' set from 'my-kubegres' to 'changed-kubegres' THEN 1 primary and 2 replica should be re-deployed with spec 'serviceAccountName' set to 'changed-kubegres'", func() { + + log.Print("START OF: Test 'GIVEN existing Kubegres is updated with spec 'serviceAccountName' set from 'my-kubegres' to 'changed-kubegres'") + + test.whenServiceAccountIsCreated("changed-kubegres") + + test.givenExistingKubegresSpecIsSetTo("changed-kubegres") + + test.whenKubernetesIsUpdated() + + test.thenPodsStatesShouldBe("changed-kubegres", 1, 2) + + test.thenDeployedKubegresSpecShouldBeSetTo("changed-kubegres") + + test.dbQueryTestCases.ThenWeCanSqlQueryPrimaryDb() + test.dbQueryTestCases.ThenWeCanSqlQueryReplicaDb() + + log.Print("END OF: Test 'GIVEN existing Kubegres is updated with spec 'serviceAccountName' set from 'my-kubegres' to 'changed-kubegres'") + }) + }) + +}) + +type SpecServiceAccountNameTest struct { + keepCreatedResourcesForNextTest bool + kubegresResource *postgresv1.Kubegres + dbQueryTestCases testcases.DbQueryTestCases + resourceCreator util.TestResourceCreator + resourceRetriever util.TestResourceRetriever +} + +func (r *SpecServiceAccountNameTest) givenNewKubegresSpecIsSetTo(serviceAccountName string, specNbreReplicas int32) { + r.kubegresResource = resourceConfigs.LoadKubegresYaml() + r.kubegresResource.Spec.Replicas = &specNbreReplicas + if serviceAccountName != "" { + r.kubegresResource.Spec.ServiceAccountName = serviceAccountName + } +} + +func (r *SpecServiceAccountNameTest) givenExistingKubegresSpecIsSetTo(serviceAccountName string) { + var err error + r.kubegresResource, err = r.resourceRetriever.GetKubegres() + + if err != nil { + log.Println("Error while getting Kubegres resource : ", err) + Expect(err).Should(Succeed()) + return + } + + r.kubegresResource.Spec.ServiceAccountName = serviceAccountName +} + +func (r *SpecServiceAccountNameTest) whenKubegresIsCreated() { + r.resourceCreator.CreateKubegres(r.kubegresResource) +} + +func (r *SpecServiceAccountNameTest) whenKubernetesIsUpdated() { + r.resourceCreator.UpdateResource(r.kubegresResource, "Kubegres") +} + +func (r *SpecServiceAccountNameTest) thenPodsStatesShouldBe(serviceAccountName string, nbrePrimary, nbreReplicas int) bool { + return Eventually(func() bool { + + kubegresResources, err := r.resourceRetriever.GetKubegresResources() + if err != nil && !apierrors.IsNotFound(err) { + log.Println("ERROR while retrieving Kubegres kubegresResources") + return false + } + + for _, resource := range kubegresResources.Resources { + currentServiceAccountName := resource.Pod.Spec.ServiceAccountName + if currentServiceAccountName != serviceAccountName { + log.Println("Pod '" + resource.Pod.Name + "' doesn't have the expected serviceAccountName: '" + serviceAccountName + "'. " + + "Current value: '" + currentServiceAccountName + "'. Waiting...") + return false + } + } + + if kubegresResources.AreAllReady && + kubegresResources.NbreDeployedPrimary == nbrePrimary && + kubegresResources.NbreDeployedReplicas == nbreReplicas { + + time.Sleep(resourceConfigs.TestRetryInterval) + log.Println("Deployed and Ready StatefulSets check successful") + return true + } + + return false + + }, resourceConfigs.TestTimeout, resourceConfigs.TestRetryInterval).Should(BeTrue()) +} + +func (r *SpecServiceAccountNameTest) thenDeployedKubegresSpecShouldBeSetTo(serviceAccountName string) { + var err error + r.kubegresResource, err = r.resourceRetriever.GetKubegres() + + if err != nil { + log.Println("Error while getting Kubegres resource : ", err) + Expect(err).Should(Succeed()) + return + } + + Expect(r.kubegresResource.Spec.ServiceAccountName).Should(Equal(serviceAccountName)) +} + +func (r *SpecServiceAccountNameTest) whenServiceAccountIsCreated(serviceAccountName string) { + r.resourceCreator.CreateServiceAccount(serviceAccountName) +} diff --git a/internal/test/util/TestResourceCreator.go b/internal/test/util/TestResourceCreator.go index cb3adda..523fd46 100644 --- a/internal/test/util/TestResourceCreator.go +++ b/internal/test/util/TestResourceCreator.go @@ -22,17 +22,18 @@ package util import ( "context" + "log" + "strconv" + "time" + "github.com/onsi/gomega" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "log" postgresv1 "reactive-tech.io/kubegres/api/v1" "reactive-tech.io/kubegres/internal/test/resourceConfigs" "sigs.k8s.io/controller-runtime/pkg/client" - "strconv" - "time" ) type TestResourceCreator struct { @@ -184,6 +185,24 @@ func (r *TestResourceCreator) CreateServiceToSqlQueryDb(kubegresName string, nod return r.createResourceFromYaml(resourceLabel, serviceResourceName, &existingResource, &resourceToCreate) } +func (r *TestResourceCreator) CreateServiceAccount(serviceAccountName string) { + existingResource := v1.ServiceAccount{} + resourceToCreate := resourceConfigs.LoadServiceAccountYaml() + resourceToCreate.Namespace = r.namespace + resourceToCreate.Name = resourceConfigs.ServiceAccountResourceName + + if serviceAccountName != "" { + resourceToCreate.Name = serviceAccountName + } + _, err := r.createResourceFromYaml("ServiceAccount", resourceToCreate.Name, &existingResource, &resourceToCreate) + if err != nil { + log.Println("Error while creating ServiceAccount resource : ", err) + gomega.Expect(err).Should(gomega.Succeed()) + } else { + log.Println("ServiceAccount resource created") + } +} + func (r *TestResourceCreator) DeleteResource(resourceToDelete client.Object, resourceName string) bool { ctx := context.Background() err := r.client.Delete(ctx, resourceToDelete)