Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to read the operator namespace from an envirnment variable… #51

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/utils/testfiles/namespace
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
testnamespace
3 changes: 3 additions & 0 deletions internal/utils/testfiles/namespaceWithSpaces
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
testnamespace


26 changes: 25 additions & 1 deletion internal/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,41 @@ import (
"strings"
)

const (
// SAFileDefaultLocation default location of the service account namespace file
SAFileDefaultLocation = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"

// SAFileLocationEnv is the name of the environment variable that holds the service
// account file location file. It is not set by default, but setting it allows operator
// developers set different file location, because the default path may not be accessible
// on the development environment. If not set, the default path will be used.
SAFileLocationEnv = "SA_FILE_PATH"

// OperatorNamespaceEnv the name of the environm,ent variable that holds the namespace.
// If set, the GetOperatorNamespace method returns its value. If not, the method read the
// service account file.
OperatorNamespaceEnv = "OPERATOR_NAMESPACE"
)

// ErrNoNamespace indicates that a namespace could not be found for the current
// environment
var ErrNoNamespace = fmt.Errorf("namespace not found for current environment")

var readSAFile = func() ([]byte, error) {
return ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
saFileLocation, found := os.LookupEnv(SAFileLocationEnv)
if !found {
saFileLocation = SAFileDefaultLocation
}
return ioutil.ReadFile(saFileLocation)
}

// GetOperatorNamespace returns the namespace the operator should be running in from
// the associated service account secret.
var GetOperatorNamespace = func() (string, error) {
if ns := strings.TrimSpace(os.Getenv(OperatorNamespaceEnv)); ns != "" {
return ns, nil
}

nsBytes, err := readSAFile()
if err != nil {
if os.IsNotExist(err) {
Expand Down
121 changes: 116 additions & 5 deletions internal/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ package utils

import (
"os"
"strings"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("Helpers test", func() {
Describe("GetOperatorNamespace", func() {
var origReadSAFile = readSAFile
AfterEach(func() {
readSAFile = origReadSAFile
})
const testNamespace = "testnamespace"
It("should return error when namespace not found", func() {
readSAFile = func() ([]byte, error) {
return nil, os.ErrNotExist
Expand All @@ -33,24 +39,129 @@ var _ = Describe("Helpers test", func() {
})
It("should return namespace", func() {
readSAFile = func() ([]byte, error) {
return []byte("testnamespace"), nil
return []byte(testNamespace), nil
}

// test
namespace, err := GetOperatorNamespace()
Expect(err).Should(BeNil())
Expect(namespace).To(Equal("testnamespace"))
Expect(namespace).To(Equal(testNamespace))
})
It("should trim whitespace from namespace", func() {
readSAFile = func() ([]byte, error) {
return []byte(" testnamespace "), nil
return []byte(" " + testNamespace + " "), nil
}

// test
namespace, err := GetOperatorNamespace()
Expect(err).Should(BeNil())
Expect(namespace).To(Equal("testnamespace"))
Expect(err).ShouldNot(HaveOccurred())
Expect(namespace).To(Equal(testNamespace))
})
Context("read namespace from environment variable", func() {
var originalVal string
JustBeforeEach(func() {
originalVal = os.Getenv(OperatorNamespaceEnv)
})
JustAfterEach(func() {
err := os.Setenv(OperatorNamespaceEnv, originalVal)
Expect(err).ShouldNot(HaveOccurred())
})
It("should return the env var value, if set", func() {
err := os.Setenv(OperatorNamespaceEnv, testNamespace)
Expect(err).ShouldNot(HaveOccurred())

namespace, err := GetOperatorNamespace()
Expect(err).ShouldNot(HaveOccurred())
Expect(namespace).To(Equal(testNamespace))
})
It("should trim spaces from the namespace", func() {
err := os.Setenv(OperatorNamespaceEnv, " "+testNamespace+" ")
Expect(err).ShouldNot(HaveOccurred())

namespace, err := GetOperatorNamespace()
Expect(err).ShouldNot(HaveOccurred())
Expect(namespace).To(Equal(testNamespace))
})
It("should return the namespace from a file if not the env var is not set", func() {
readSAFile = func() ([]byte, error) {
return []byte("namespace-from-file"), nil
}
err := os.Unsetenv(OperatorNamespaceEnv)
Expect(err).ShouldNot(HaveOccurred())

namespace, err := GetOperatorNamespace()
Expect(err).Should(BeNil())
Expect(namespace).To(Equal("namespace-from-file"))

})
It("should return the namespace from a file if not the env var is only spaces", func() {
readSAFile = func() ([]byte, error) {
return []byte("namespace-from-file"), nil
}
err := os.Setenv(OperatorNamespaceEnv, " ")
Expect(err).ShouldNot(HaveOccurred())

namespace, err := GetOperatorNamespace()
Expect(err).Should(BeNil())
Expect(namespace).To(Equal("namespace-from-file"))
})
})
Context("read namespace from non standard location", func() {
var originalVal string
JustBeforeEach(func() {
originalVal = os.Getenv(SAFileLocationEnv)
})
JustAfterEach(func() {
err := os.Setenv(SAFileLocationEnv, originalVal)
Expect(err).ShouldNot(HaveOccurred())
})
It("should return the env var value, if set", func() {
err := os.Setenv(SAFileLocationEnv, getTestFilesDir()+"namespace")
Expect(err).ShouldNot(HaveOccurred())

namespace, err := GetOperatorNamespace()
Expect(err).ShouldNot(HaveOccurred())
Expect(namespace).To(Equal(testNamespace))
})
It("should trim spaces from the namespace", func() {
err := os.Setenv(SAFileLocationEnv, getTestFilesDir()+"namespaceWithSpaces")
Expect(err).ShouldNot(HaveOccurred())

namespace, err := GetOperatorNamespace()
Expect(err).ShouldNot(HaveOccurred())

Expect(namespace).To(Equal(testNamespace))
})
It("should return error if the file is not exists", func() {
err := os.Setenv(SAFileLocationEnv, getTestFilesDir()+"notExists")
Expect(err).ShouldNot(HaveOccurred())

namespace, err := GetOperatorNamespace()
Expect(err).Should(HaveOccurred())
Expect(err).Should(Equal(ErrNoNamespace))

Expect(namespace).Should(BeEmpty())
})
})
})

})

// return the path to the test files directory
func getTestFilesDir() string {
const (
packageUnderTestPath = "internal/utils"
testFileDir = "/testfiles/"
)

wd, err := os.Getwd()
ExpectWithOffset(1, err).ShouldNot(HaveOccurred())

// if running form internal/utils/
if strings.HasSuffix(wd, packageUnderTestPath) {
return wd + testFileDir
}

// if running from repository root
return packageUnderTestPath + testFileDir
}