Extend functionality of kubernetes-entrypoint with adding namespace per service option.
This commit is contained in:
parent
ff51e34598
commit
2590d0c013
49
.gitignore
vendored
Normal file
49
.gitignore
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff:
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/dictionaries
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.xml
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# CMake
|
||||
cmake-build-debug/
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
11
README.md
11
README.md
@ -26,6 +26,17 @@ There is only one required environment variable "COMMAND" which specifies a comm
|
||||
|
||||
Kubernetes-entrypoint introduces a wide variety of dependencies which can be used to better orchestrate once deployment.
|
||||
|
||||
## Latest features
|
||||
|
||||
Extending functionality of kubernetes-entrypoint by adding an ability to specify dependencies in different namespaces. The new format for writing dependencies is `namespace:name`. To ensure backward compatibility if the dependency name is without colon, it behaves just like in previous versions so it esumes that dependecies is running at the same namespace as kubernetes-entrypoint. This feature is not implemented for container, config and socket dependency because in such cases the different namespace is irrelevant.
|
||||
|
||||
For instance:
|
||||
`
|
||||
DEPENDENCY_SERVICE=mysql:mariadb,keystone-api
|
||||
`
|
||||
|
||||
The new entrypoint will resolve mariadb in mysql namespace and keystone-api in the same namespace as entrypoint was deployed in.
|
||||
|
||||
## Supported types of dependencies
|
||||
|
||||
All dependencies are passed as environement variables in format of `DEPENDENCY_<NAME>` delimited by colon. For dependencies to be effective please use [readiness probes](http://kubernetes.io/docs/user-guide/production-pods/#liveness-and-readiness-probes-aka-health-checks) for all containers.
|
||||
|
25
dependencies/config/config.go
vendored
25
dependencies/config/config.go
vendored
@ -13,7 +13,10 @@ import (
|
||||
"github.com/stackanetes/kubernetes-entrypoint/util/env"
|
||||
)
|
||||
|
||||
const configmapDirPrefix = "/configmaps"
|
||||
const (
|
||||
configmapDirPrefix = "/configmaps"
|
||||
NamespaceNotSupported = "Config doesn't accept namespace"
|
||||
)
|
||||
|
||||
type configParams struct {
|
||||
HOSTNAME string
|
||||
@ -29,9 +32,13 @@ type Config struct {
|
||||
|
||||
func init() {
|
||||
configEnv := fmt.Sprintf("%sCONFIG", entry.DependencyPrefix)
|
||||
if configDeps := env.SplitEnvToList(configEnv); len(configDeps) > 0 {
|
||||
if util.ContainsSeparator(configEnv, "Config") {
|
||||
logger.Error.Printf(NamespaceNotSupported)
|
||||
os.Exit(1)
|
||||
}
|
||||
if configDeps := env.SplitEnvToDeps(configEnv); len(configDeps) > 0 {
|
||||
for _, dep := range configDeps {
|
||||
config, err := NewConfig(dep, configmapDirPrefix)
|
||||
config, err := NewConfig(dep.Name, configmapDirPrefix)
|
||||
if err != nil {
|
||||
logger.Error.Printf("Cannot initialize config dep: %v", err)
|
||||
}
|
||||
@ -63,11 +70,11 @@ func NewConfig(name string, prefix string) (*Config, error) {
|
||||
|
||||
func (c Config) IsResolved(entrypoint entry.EntrypointInterface) (bool, error) {
|
||||
//Create directory to ensure it exists
|
||||
if err := createDirectory(c.GetName()); err != nil {
|
||||
if err := createDirectory(c.name); err != nil {
|
||||
return false, fmt.Errorf("Couldn't create directory: %v", err)
|
||||
}
|
||||
if err := c.createAndTemplateConfig(); err != nil {
|
||||
return false, fmt.Errorf("Cannot template %s: %v", c.GetName(), err)
|
||||
return false, fmt.Errorf("Cannot template %s: %v", c.name, err)
|
||||
}
|
||||
return true, nil
|
||||
|
||||
@ -87,10 +94,6 @@ func (c Config) createAndTemplateConfig() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c Config) GetName() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func getSrcConfig(prefix string, config string) (srcConfig string) {
|
||||
return fmt.Sprintf("%s/%s/%s", prefix, config, config)
|
||||
}
|
||||
@ -98,3 +101,7 @@ func getSrcConfig(prefix string, config string) (srcConfig string) {
|
||||
func createDirectory(file string) error {
|
||||
return os.MkdirAll(filepath.Dir(file), 0755)
|
||||
}
|
||||
|
||||
func (c Config) String() string {
|
||||
return fmt.Sprintf("Config %s", c.name)
|
||||
}
|
||||
|
11
dependencies/config/config_test.go
vendored
11
dependencies/config/config_test.go
vendored
@ -1,4 +1,4 @@
|
||||
package config_test
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -7,7 +7,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
. "github.com/stackanetes/kubernetes-entrypoint/dependencies/config"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/entrypoint"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/mocks"
|
||||
|
||||
@ -22,7 +21,6 @@ const (
|
||||
|
||||
testConfigContentsFormat = "TEST_CONFIG %s\n"
|
||||
|
||||
// configPath = "/tmp/lgtm"
|
||||
templatePrefix = "/tmp/templates"
|
||||
)
|
||||
|
||||
@ -111,9 +109,11 @@ var _ = Describe("Config", func() {
|
||||
})
|
||||
|
||||
It("checks the name of a newly created config file", func() {
|
||||
config, _ := NewConfig(testConfigPath, templatePrefix)
|
||||
config, err := NewConfig(testConfigPath, templatePrefix)
|
||||
Expect(config.name).To(Equal(testConfigPath))
|
||||
|
||||
Expect(config.GetName()).To(Equal(testConfigPath))
|
||||
Expect(config).NotTo(Equal(nil))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("checks the format of a newly created config file", func() {
|
||||
@ -137,5 +137,4 @@ var _ = Describe("Config", func() {
|
||||
Expect(isResolved).To(Equal(true))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
})
|
||||
|
34
dependencies/container/container.go
vendored
34
dependencies/container/container.go
vendored
@ -4,11 +4,18 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"strings"
|
||||
|
||||
entry "github.com/stackanetes/kubernetes-entrypoint/entrypoint"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/logger"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/util"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/util/env"
|
||||
)
|
||||
|
||||
const PodNameNotSetError = "Environment variable POD_NAME not set"
|
||||
const (
|
||||
PodNameNotSetError = "Environment variable POD_NAME not set"
|
||||
NamespaceNotSupported = "Container doesn't accept namespace"
|
||||
)
|
||||
|
||||
type Container struct {
|
||||
name string
|
||||
@ -16,9 +23,16 @@ type Container struct {
|
||||
|
||||
func init() {
|
||||
containerEnv := fmt.Sprintf("%sCONTAINER", entry.DependencyPrefix)
|
||||
if containerDeps := env.SplitEnvToList(containerEnv); len(containerDeps) > 0 {
|
||||
for _, dep := range containerDeps {
|
||||
entry.Register(NewContainer(dep))
|
||||
if util.ContainsSeparator(containerEnv, "Container") {
|
||||
logger.Error.Printf(NamespaceNotSupported)
|
||||
os.Exit(1)
|
||||
}
|
||||
if containerDeps := env.SplitEnvToDeps(containerEnv); containerDeps != nil {
|
||||
|
||||
if len(containerDeps) > 0 {
|
||||
for _, dep := range containerDeps {
|
||||
entry.Register(NewContainer(dep.Name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,19 +47,23 @@ func (c Container) IsResolved(entrypoint entry.EntrypointInterface) (bool, error
|
||||
if myPodName == "" {
|
||||
return false, fmt.Errorf(PodNameNotSetError)
|
||||
}
|
||||
pod, err := entrypoint.Client().Pods(entrypoint.GetNamespace()).Get(myPodName)
|
||||
pod, err := entrypoint.Client().Pods(env.GetBaseNamespace()).Get(myPodName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if strings.Contains(c.name, env.Separator) {
|
||||
return false, fmt.Errorf("Specifing namespace is not permitted")
|
||||
}
|
||||
containers := pod.Status.ContainerStatuses
|
||||
for _, container := range containers {
|
||||
if container.Name == c.GetName() && container.Ready {
|
||||
if container.Name == c.name && container.Ready {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (c Container) GetName() string {
|
||||
return c.name
|
||||
func (c Container) String() string {
|
||||
return fmt.Sprintf("Container %s", c.name)
|
||||
}
|
||||
|
5
dependencies/container/container_test.go
vendored
5
dependencies/container/container_test.go
vendored
@ -1,10 +1,9 @@
|
||||
package container_test
|
||||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
. "github.com/stackanetes/kubernetes-entrypoint/dependencies/container"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/entrypoint"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/mocks"
|
||||
|
||||
@ -30,7 +29,7 @@ var _ = Describe("Container", func() {
|
||||
It("checks the name of a newly created container", func() {
|
||||
container := NewContainer(mocks.MockContainerName)
|
||||
|
||||
Expect(container.GetName()).To(Equal(mocks.MockContainerName))
|
||||
Expect(container.name).To(Equal(mocks.MockContainerName))
|
||||
})
|
||||
|
||||
It(fmt.Sprintf("checks container resolution failure with %s not set", podEnvVariableName), func() {
|
||||
|
36
dependencies/daemonset/daemonset.go
vendored
36
dependencies/daemonset/daemonset.go
vendored
@ -14,19 +14,20 @@ import (
|
||||
|
||||
const (
|
||||
PodNameEnvVar = "POD_NAME"
|
||||
PodNameNotSetErrorFormat = "Env POD_NAME not set. Daemonset dependency %s will be ignored!"
|
||||
PodNameNotSetErrorFormat = "Env POD_NAME not set. Daemonset dependency %s in namespace %s will be ignored!"
|
||||
)
|
||||
|
||||
type Daemonset struct {
|
||||
name string
|
||||
podName string
|
||||
name string
|
||||
namespace string
|
||||
podName string
|
||||
}
|
||||
|
||||
func init() {
|
||||
daemonsetEnv := fmt.Sprintf("%sDAEMONSET", entry.DependencyPrefix)
|
||||
if daemonsetsDeps := env.SplitEnvToList(daemonsetEnv); daemonsetsDeps != nil {
|
||||
if daemonsetsDeps := env.SplitEnvToDeps(daemonsetEnv); daemonsetsDeps != nil {
|
||||
for _, dep := range daemonsetsDeps {
|
||||
daemonset, err := NewDaemonset(dep)
|
||||
daemonset, err := NewDaemonset(dep.Name, dep.Namespace)
|
||||
if err != nil {
|
||||
logger.Error.Printf("Cannot initialize daemonset: %v", err)
|
||||
continue
|
||||
@ -36,19 +37,20 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func NewDaemonset(name string) (*Daemonset, error) {
|
||||
func NewDaemonset(name string, namespace string) (*Daemonset, error) {
|
||||
if os.Getenv(PodNameEnvVar) == "" {
|
||||
return nil, fmt.Errorf(PodNameNotSetErrorFormat, name)
|
||||
return nil, fmt.Errorf(PodNameNotSetErrorFormat, name, namespace)
|
||||
}
|
||||
return &Daemonset{
|
||||
name: name,
|
||||
podName: os.Getenv(PodNameEnvVar),
|
||||
name: name,
|
||||
namespace: namespace,
|
||||
podName: os.Getenv(PodNameEnvVar),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d Daemonset) IsResolved(entrypoint entry.EntrypointInterface) (bool, error) {
|
||||
var myPodName string
|
||||
daemonset, err := entrypoint.Client().DaemonSets(entrypoint.GetNamespace()).Get(d.GetName())
|
||||
daemonset, err := entrypoint.Client().DaemonSets(d.namespace).Get(d.name)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -56,12 +58,12 @@ func (d Daemonset) IsResolved(entrypoint entry.EntrypointInterface) (bool, error
|
||||
|
||||
label := labels.SelectorFromSet(daemonset.Spec.Selector.MatchLabels)
|
||||
opts := api.ListOptions{LabelSelector: label}
|
||||
pods, err := entrypoint.Client().Pods(entrypoint.GetNamespace()).List(opts)
|
||||
pods, err := entrypoint.Client().Pods(d.namespace).List(opts)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
myPod, err := entrypoint.Client().Pods(entrypoint.GetNamespace()).Get(d.podName)
|
||||
myPod, err := entrypoint.Client().Pods(d.namespace).Get(d.podName)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Getting POD: %v failed : %v", myPodName, err)
|
||||
}
|
||||
@ -75,16 +77,12 @@ func (d Daemonset) IsResolved(entrypoint entry.EntrypointInterface) (bool, error
|
||||
if isPodReady(pod) {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("Pod %v of daemonset %v is not ready", pod.Name, d.GetName())
|
||||
return false, fmt.Errorf("Pod %v of daemonset %s is not ready", pod.Name, d)
|
||||
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (d Daemonset) GetName() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
func isPodOnHost(pod *v1.Pod, hostIP string) bool {
|
||||
if pod.Status.HostIP == hostIP {
|
||||
return true
|
||||
@ -100,3 +98,7 @@ func isPodReady(pod v1.Pod) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d Daemonset) String() string {
|
||||
return fmt.Sprintf("Daemonset %s in namespace %s", d.name, d.namespace)
|
||||
}
|
||||
|
47
dependencies/daemonset/daemonset_test.go
vendored
47
dependencies/daemonset/daemonset_test.go
vendored
@ -1,10 +1,9 @@
|
||||
package daemonset_test
|
||||
package daemonset
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
. "github.com/stackanetes/kubernetes-entrypoint/dependencies/daemonset"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/entrypoint"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/mocks"
|
||||
|
||||
@ -14,6 +13,7 @@ import (
|
||||
|
||||
const (
|
||||
podEnvVariableValue = "podlist"
|
||||
daemonsetNamespace = "namespace1"
|
||||
)
|
||||
|
||||
var testEntrypoint entrypoint.EntrypointInterface
|
||||
@ -29,22 +29,22 @@ var _ = Describe("Daemonset", func() {
|
||||
|
||||
It(fmt.Sprintf("checks failure of new daemonset creation without %s set", PodNameEnvVar), func() {
|
||||
os.Unsetenv(PodNameEnvVar)
|
||||
daemonset, err := NewDaemonset(mocks.SucceedingDaemonsetName)
|
||||
daemonset, err := NewDaemonset(mocks.SucceedingDaemonsetName, daemonsetNamespace)
|
||||
|
||||
Expect(daemonset).To(BeNil())
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(PodNameNotSetErrorFormat, mocks.SucceedingDaemonsetName)))
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(PodNameNotSetErrorFormat, mocks.SucceedingDaemonsetName, daemonsetNamespace)))
|
||||
})
|
||||
|
||||
It(fmt.Sprintf("creates new daemonset with %s set and checks its name", PodNameEnvVar), func() {
|
||||
daemonset, err := NewDaemonset(mocks.SucceedingDaemonsetName)
|
||||
daemonset, err := NewDaemonset(mocks.SucceedingDaemonsetName, daemonsetNamespace)
|
||||
Expect(daemonset).NotTo(Equal(nil))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(daemonset.GetName()).To(Equal(mocks.SucceedingDaemonsetName))
|
||||
Expect(daemonset.name).To(Equal(mocks.SucceedingDaemonsetName))
|
||||
})
|
||||
|
||||
It("checks resolution of a succeeding daemonset", func() {
|
||||
daemonset, _ := NewDaemonset(mocks.SucceedingDaemonsetName)
|
||||
daemonset, _ := NewDaemonset(mocks.SucceedingDaemonsetName, daemonsetNamespace)
|
||||
|
||||
isResolved, err := daemonset.IsResolved(testEntrypoint)
|
||||
|
||||
@ -53,7 +53,7 @@ var _ = Describe("Daemonset", func() {
|
||||
})
|
||||
|
||||
It("checks resolution failure of a daemonset with incorrect name", func() {
|
||||
daemonset, _ := NewDaemonset(mocks.FailingDaemonsetName)
|
||||
daemonset, _ := NewDaemonset(mocks.FailingDaemonsetName, daemonsetNamespace)
|
||||
|
||||
isResolved, err := daemonset.IsResolved(testEntrypoint)
|
||||
|
||||
@ -62,7 +62,7 @@ var _ = Describe("Daemonset", func() {
|
||||
})
|
||||
|
||||
It("checks resolution failure of a daemonset with incorrect match labels", func() {
|
||||
daemonset, _ := NewDaemonset(mocks.IncorrectMatchLabelsDaemonsetName)
|
||||
daemonset, _ := NewDaemonset(mocks.IncorrectMatchLabelsDaemonsetName, daemonsetNamespace)
|
||||
|
||||
isResolved, err := daemonset.IsResolved(testEntrypoint)
|
||||
|
||||
@ -73,7 +73,7 @@ var _ = Describe("Daemonset", func() {
|
||||
It(fmt.Sprintf("checks resolution failure of a daemonset with incorrect %s value", PodNameEnvVar), func() {
|
||||
// Set POD_NAME to value not present in the mocks
|
||||
os.Setenv(PodNameEnvVar, mocks.PodNotPresent)
|
||||
daemonset, _ := NewDaemonset(mocks.IncorrectMatchLabelsDaemonsetName)
|
||||
daemonset, _ := NewDaemonset(mocks.IncorrectMatchLabelsDaemonsetName, daemonsetNamespace)
|
||||
|
||||
isResolved, err := daemonset.IsResolved(testEntrypoint)
|
||||
|
||||
@ -82,7 +82,32 @@ var _ = Describe("Daemonset", func() {
|
||||
})
|
||||
|
||||
It("checks resolution failure of a daemonset with none of the pods with Ready status", func() {
|
||||
daemonset, _ := NewDaemonset(mocks.NotReadyMatchLabelsDaemonsetName)
|
||||
daemonset, _ := NewDaemonset(mocks.NotReadyMatchLabelsDaemonsetName, daemonsetNamespace)
|
||||
|
||||
isResolved, err := daemonset.IsResolved(testEntrypoint)
|
||||
|
||||
Expect(isResolved).To(Equal(false))
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("checks resolution of a correct daemonset namespace", func() {
|
||||
daemonset, err := NewDaemonset(mocks.CorrectDaemonsetNamespace, daemonsetNamespace)
|
||||
|
||||
Expect(daemonset).NotTo(Equal(nil))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
isResolved, err := daemonset.IsResolved(testEntrypoint)
|
||||
|
||||
Expect(isResolved).To(Equal(true))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
})
|
||||
|
||||
It("checks resolution of an incorrect daemonset namespace", func() {
|
||||
daemonset, err := NewDaemonset(mocks.IncorrectDaemonsetNamespace, daemonsetNamespace)
|
||||
|
||||
Expect(daemonset).NotTo(Equal(nil))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
isResolved, err := daemonset.IsResolved(testEntrypoint)
|
||||
|
||||
|
28
dependencies/job/job.go
vendored
28
dependencies/job/job.go
vendored
@ -7,37 +7,43 @@ import (
|
||||
"github.com/stackanetes/kubernetes-entrypoint/util/env"
|
||||
)
|
||||
|
||||
const FailingStatusFormat = "Job %v is not completed yet"
|
||||
const FailingStatusFormat = "Job %s is not completed yet"
|
||||
|
||||
type Job struct {
|
||||
name string
|
||||
name string
|
||||
namespace string
|
||||
}
|
||||
|
||||
func init() {
|
||||
jobsEnv := fmt.Sprintf("%sJOBS", entry.DependencyPrefix)
|
||||
if jobsDeps := env.SplitEnvToList(jobsEnv); len(jobsDeps) > 0 {
|
||||
for _, dep := range jobsDeps {
|
||||
entry.Register(NewJob(dep))
|
||||
if jobsDeps := env.SplitEnvToDeps(jobsEnv); jobsDeps != nil {
|
||||
if len(jobsDeps) > 0 {
|
||||
for _, dep := range jobsDeps {
|
||||
entry.Register(NewJob(dep.Name, dep.Namespace))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewJob(name string) Job {
|
||||
return Job{name: name}
|
||||
func NewJob(name string, namespace string) Job {
|
||||
return Job{
|
||||
name: name,
|
||||
namespace: namespace,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (j Job) IsResolved(entrypoint entry.EntrypointInterface) (bool, error) {
|
||||
job, err := entrypoint.Client().Jobs(entrypoint.GetNamespace()).Get(j.GetName())
|
||||
job, err := entrypoint.Client().Jobs(j.namespace).Get(j.name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if job.Status.Succeeded == 0 {
|
||||
return false, fmt.Errorf(FailingStatusFormat, j.GetName())
|
||||
return false, fmt.Errorf(FailingStatusFormat, j)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (j Job) GetName() string {
|
||||
return j.name
|
||||
func (j Job) String() string {
|
||||
return fmt.Sprintf("Job %s in namespace %s", j.name, j.namespace)
|
||||
}
|
||||
|
18
dependencies/job/job_test.go
vendored
18
dependencies/job/job_test.go
vendored
@ -1,9 +1,8 @@
|
||||
package job_test
|
||||
package job
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/stackanetes/kubernetes-entrypoint/dependencies/job"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/entrypoint"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/mocks"
|
||||
|
||||
@ -11,7 +10,8 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
const testJobName = "TEST_JOB"
|
||||
const testJobName = "TEST_JOB_NAME"
|
||||
const testJobNamespace = "TEST_JOB_NAMESPACE"
|
||||
|
||||
var testEntrypoint entrypoint.EntrypointInterface
|
||||
|
||||
@ -22,13 +22,14 @@ var _ = Describe("Job", func() {
|
||||
})
|
||||
|
||||
It("checks the name of a newly created job", func() {
|
||||
job := NewJob(testJobName)
|
||||
job := NewJob(testJobName, testJobNamespace)
|
||||
|
||||
Expect(job.GetName()).To(Equal(testJobName))
|
||||
Expect(job.name).To(Equal(testJobName))
|
||||
Expect(job.namespace).To(Equal(testJobNamespace))
|
||||
})
|
||||
|
||||
It("checks resolution of a succeeding job", func() {
|
||||
job := NewJob(mocks.SucceedingJobName)
|
||||
job := NewJob(mocks.SucceedingJobName, mocks.SucceedingJobName)
|
||||
|
||||
isResolved, err := job.IsResolved(testEntrypoint)
|
||||
|
||||
@ -37,11 +38,12 @@ var _ = Describe("Job", func() {
|
||||
})
|
||||
|
||||
It("checks resolution failure of a failing job", func() {
|
||||
job := NewJob(mocks.FailingJobName)
|
||||
job := NewJob(mocks.FailingJobName, mocks.FailingJobName)
|
||||
|
||||
isResolved, err := job.IsResolved(testEntrypoint)
|
||||
|
||||
Expect(isResolved).To(Equal(false))
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(FailingStatusFormat, job.GetName())))
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(FailingStatusFormat, job)))
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(FailingStatusFormat, job)))
|
||||
})
|
||||
})
|
||||
|
26
dependencies/service/service.go
vendored
26
dependencies/service/service.go
vendored
@ -10,25 +10,31 @@ import (
|
||||
const FailingStatusFormat = "Service %v has no endpoints"
|
||||
|
||||
type Service struct {
|
||||
name string
|
||||
name string
|
||||
namespace string
|
||||
}
|
||||
|
||||
func init() {
|
||||
serviceEnv := fmt.Sprintf("%sSERVICE", entry.DependencyPrefix)
|
||||
if serviceDeps := env.SplitEnvToList(serviceEnv); len(serviceDeps) > 0 {
|
||||
for _, dep := range serviceDeps {
|
||||
entry.Register(NewService(dep))
|
||||
if serviceDeps := env.SplitEnvToDeps(serviceEnv); serviceDeps != nil {
|
||||
if len(serviceDeps) > 0 {
|
||||
for _, dep := range serviceDeps {
|
||||
entry.Register(NewService(dep.Name, dep.Namespace))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewService(name string) Service {
|
||||
return Service{name: name}
|
||||
func NewService(name string, namespace string) Service {
|
||||
return Service{
|
||||
name: name,
|
||||
namespace: namespace,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s Service) IsResolved(entrypoint entry.EntrypointInterface) (bool, error) {
|
||||
e, err := entrypoint.Client().Endpoints(entrypoint.GetNamespace()).Get(s.GetName())
|
||||
e, err := entrypoint.Client().Endpoints(s.namespace).Get(s.name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -38,9 +44,9 @@ func (s Service) IsResolved(entrypoint entry.EntrypointInterface) (bool, error)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, fmt.Errorf(FailingStatusFormat, s.GetName())
|
||||
return false, fmt.Errorf(FailingStatusFormat, s.name)
|
||||
}
|
||||
|
||||
func (s Service) GetName() string {
|
||||
return s.name
|
||||
func (s Service) String() string {
|
||||
return fmt.Sprintf("Service %s in namespace %s", s.name, s.namespace)
|
||||
}
|
||||
|
19
dependencies/service/service_test.go
vendored
19
dependencies/service/service_test.go
vendored
@ -1,9 +1,8 @@
|
||||
package service_test
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/stackanetes/kubernetes-entrypoint/dependencies/service"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/entrypoint"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/mocks"
|
||||
|
||||
@ -11,7 +10,8 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
const testServiceName = "TEST_SERVICE"
|
||||
const testServiceName = "TEST_SERVICE_NAME"
|
||||
const testServiceNamespace = "TEST_SERVICE_NAMESPACE"
|
||||
|
||||
var testEntrypoint entrypoint.EntrypointInterface
|
||||
|
||||
@ -22,13 +22,14 @@ var _ = Describe("Service", func() {
|
||||
})
|
||||
|
||||
It("checks the name of a newly created service", func() {
|
||||
service := NewService(testServiceName)
|
||||
service := NewService(testServiceName, testServiceNamespace)
|
||||
|
||||
Expect(service.GetName()).To(Equal(testServiceName))
|
||||
Expect(service.name).To(Equal(testServiceName))
|
||||
Expect(service.namespace).To(Equal(testServiceNamespace))
|
||||
})
|
||||
|
||||
It("checks resolution of a succeeding service", func() {
|
||||
service := NewService(mocks.SucceedingServiceName)
|
||||
service := NewService(mocks.SucceedingServiceName, mocks.SucceedingServiceName)
|
||||
|
||||
isResolved, err := service.IsResolved(testEntrypoint)
|
||||
|
||||
@ -37,7 +38,7 @@ var _ = Describe("Service", func() {
|
||||
})
|
||||
|
||||
It("checks resolution failure of a failing service", func() {
|
||||
service := NewService(mocks.FailingServiceName)
|
||||
service := NewService(mocks.FailingServiceName, mocks.FailingServiceName)
|
||||
|
||||
isResolved, err := service.IsResolved(testEntrypoint)
|
||||
|
||||
@ -46,10 +47,10 @@ var _ = Describe("Service", func() {
|
||||
})
|
||||
|
||||
It("checks resolution failure of a succeeding service with removed subsets", func() {
|
||||
service := NewService(mocks.EmptySubsetsServiceName)
|
||||
service := NewService(mocks.EmptySubsetsServiceName, mocks.EmptySubsetsServiceName)
|
||||
|
||||
isResolved, err := service.IsResolved(testEntrypoint)
|
||||
Expect(isResolved).To(Equal(false))
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(FailingStatusFormat, service.GetName())))
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(FailingStatusFormat, service.name)))
|
||||
})
|
||||
})
|
||||
|
33
dependencies/socket/socket.go
vendored
33
dependencies/socket/socket.go
vendored
@ -5,12 +5,15 @@ import (
|
||||
"os"
|
||||
|
||||
entry "github.com/stackanetes/kubernetes-entrypoint/entrypoint"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/logger"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/util"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/util/env"
|
||||
)
|
||||
|
||||
const (
|
||||
NonExistingErrorFormat = "Socket %v doesn't exists"
|
||||
NoPermsErrorFormat = "I have no permission to %v"
|
||||
NonExistingErrorFormat = "%s doesn't exists"
|
||||
NoPermsErrorFormat = "I have no permission to %s"
|
||||
NamespaceNotSupported = "Socket doesn't accept namespace"
|
||||
)
|
||||
|
||||
type Socket struct {
|
||||
@ -19,9 +22,15 @@ type Socket struct {
|
||||
|
||||
func init() {
|
||||
socketEnv := fmt.Sprintf("%sSOCKET", entry.DependencyPrefix)
|
||||
if socketDeps := env.SplitEnvToList(socketEnv); len(socketDeps) > 0 {
|
||||
for _, dep := range socketDeps {
|
||||
entry.Register(NewSocket(dep))
|
||||
if util.ContainsSeparator(socketEnv, "Socket") {
|
||||
logger.Error.Printf(NamespaceNotSupported)
|
||||
os.Exit(1)
|
||||
}
|
||||
if socketDeps := env.SplitEnvToDeps(socketEnv); socketDeps != nil {
|
||||
if len(socketDeps) > 0 {
|
||||
for _, dep := range socketDeps {
|
||||
entry.Register(NewSocket(dep.Name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -30,20 +39,20 @@ func NewSocket(name string) Socket {
|
||||
return Socket{name: name}
|
||||
}
|
||||
|
||||
func (s Socket) GetName() string {
|
||||
return s.name
|
||||
}
|
||||
|
||||
func (s Socket) IsResolved(entrypoint entry.EntrypointInterface) (bool, error) {
|
||||
_, err := os.Stat(s.GetName())
|
||||
_, err := os.Stat(s.name)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, fmt.Errorf(NonExistingErrorFormat, s.GetName())
|
||||
return false, fmt.Errorf(NonExistingErrorFormat, s)
|
||||
}
|
||||
if os.IsPermission(err) {
|
||||
return false, fmt.Errorf(NoPermsErrorFormat, s.GetName())
|
||||
return false, fmt.Errorf(NoPermsErrorFormat, s)
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func (s Socket) String() string {
|
||||
return fmt.Sprintf("Socket %s", s.name)
|
||||
}
|
||||
|
10
dependencies/socket/socket_test.go
vendored
10
dependencies/socket/socket_test.go
vendored
@ -1,10 +1,9 @@
|
||||
package socket_test
|
||||
package socket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
. "github.com/stackanetes/kubernetes-entrypoint/dependencies/socket"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/entrypoint"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/mocks"
|
||||
|
||||
@ -33,7 +32,7 @@ var _ = Describe("Socket", func() {
|
||||
It("checks the name of a newly created socket", func() {
|
||||
socket := NewSocket(existingSocketPath)
|
||||
|
||||
Expect(socket.GetName()).To(Equal(existingSocketPath))
|
||||
Expect(socket.name).To(Equal(existingSocketPath))
|
||||
})
|
||||
|
||||
It("resolves an existing socket socket", func() {
|
||||
@ -52,7 +51,7 @@ var _ = Describe("Socket", func() {
|
||||
|
||||
Expect(isResolved).To(Equal(false))
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(NonExistingErrorFormat, socket.GetName())))
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(NonExistingErrorFormat, socket)))
|
||||
})
|
||||
|
||||
It("fails on trying to resolve a socket without permissions", func() {
|
||||
@ -62,7 +61,6 @@ var _ = Describe("Socket", func() {
|
||||
|
||||
Expect(isResolved).To(Equal(false))
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(NoPermsErrorFormat, socket.GetName())))
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(NoPermsErrorFormat, socket)))
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -1,7 +1,6 @@
|
||||
package entrypoint
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -20,13 +19,11 @@ const (
|
||||
//Resolver is an interface which all dependencies should implement
|
||||
type Resolver interface {
|
||||
IsResolved(entrypoint EntrypointInterface) (bool, error)
|
||||
GetName() string
|
||||
}
|
||||
|
||||
type EntrypointInterface interface {
|
||||
Resolve()
|
||||
Client() cli.ClientInterface
|
||||
GetNamespace() string
|
||||
}
|
||||
|
||||
// Entrypoint is a main struct which checks dependencies
|
||||
@ -51,10 +48,6 @@ func New(config *rest.Config) (entry *Entrypoint, err error) {
|
||||
return nil, err
|
||||
}
|
||||
entry.client = client
|
||||
if entry.namespace = os.Getenv("NAMESPACE"); entry.namespace == "" {
|
||||
logger.Warning.Print("NAMESPACE env not set, using default")
|
||||
entry.namespace = "default"
|
||||
}
|
||||
return entry, err
|
||||
}
|
||||
|
||||
@ -62,10 +55,6 @@ func (e Entrypoint) Client() (client cli.ClientInterface) {
|
||||
return e.client
|
||||
}
|
||||
|
||||
func (e Entrypoint) GetNamespace() string {
|
||||
return e.namespace
|
||||
}
|
||||
|
||||
//Resolve is a main loop which iterates through all dependencies and resolves them
|
||||
func (e Entrypoint) Resolve() {
|
||||
var wg sync.WaitGroup
|
||||
@ -73,16 +62,16 @@ func (e Entrypoint) Resolve() {
|
||||
wg.Add(1)
|
||||
go func(dep Resolver) {
|
||||
defer wg.Done()
|
||||
logger.Info.Printf("Resolving %s", dep.GetName())
|
||||
logger.Info.Printf("Resolving %v", dep)
|
||||
var err error
|
||||
status := false
|
||||
for status == false {
|
||||
if status, err = dep.IsResolved(e); err != nil {
|
||||
logger.Warning.Printf("Resolving dependency for %v failed: %v", dep.GetName(), err)
|
||||
logger.Warning.Printf("Resolving dependency %s failed: %v .", dep, err)
|
||||
}
|
||||
time.Sleep(resolverSleepInterval * time.Second)
|
||||
}
|
||||
logger.Info.Printf("Dependency %v is resolved", dep.GetName())
|
||||
logger.Info.Printf("Dependency %v is resolved.", dep)
|
||||
|
||||
}(dep)
|
||||
}
|
||||
|
@ -34,6 +34,10 @@ func (d dummyResolver) GetName() (name string) {
|
||||
return d.name
|
||||
}
|
||||
|
||||
func (d dummyResolver) String() string {
|
||||
return fmt.Sprintf("Dummy %s in namespace %s", d.name, d.namespace)
|
||||
}
|
||||
|
||||
func init() {
|
||||
testClient = mocks.NewClient()
|
||||
testEntrypoint = mocks.NewEntrypointInNamespace(testNamespace)
|
||||
@ -75,11 +79,6 @@ var _ = Describe("Entrypoint", func() {
|
||||
Expect(client).To(Equal(testClient))
|
||||
})
|
||||
|
||||
It("checks Namespace() method", func() {
|
||||
ns := testEntrypoint.GetNamespace()
|
||||
Expect(ns).To(Equal(testNamespace))
|
||||
})
|
||||
|
||||
It("resolves main entrypoint with a dummy dependency", func() {
|
||||
defer GinkgoRecover()
|
||||
|
||||
@ -104,6 +103,6 @@ var _ = Describe("Entrypoint", func() {
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
stdout, _ := ioutil.ReadAll(r)
|
||||
Expect(string(stdout)).To(Equal(fmt.Sprintf("%sResolving %s\n%sDependency %s is resolved\n", loggerInfoText, dummyResolverName, loggerInfoText, dummyResolverName)))
|
||||
Expect(string(stdout)).To(Equal(fmt.Sprintf("%sResolving %v\n%sDependency %v is resolved.\n", loggerInfoText, dummy, loggerInfoText, dummy)))
|
||||
})
|
||||
})
|
||||
|
BIN
kubernetes-entrypoint
Executable file
BIN
kubernetes-entrypoint
Executable file
Binary file not shown.
@ -27,7 +27,7 @@ func main() {
|
||||
|
||||
entrypoint.Resolve()
|
||||
|
||||
if comm = env.SplitEnvToList("COMMAND", " "); len(comm) == 0 {
|
||||
if comm = env.SplitCommand(); len(comm) == 0 {
|
||||
// TODO(DTadrzak): we should consider other options to handle whether pod
|
||||
// is an init-container
|
||||
logger.Warning.Printf("COMMAND env is empty")
|
||||
|
@ -41,6 +41,12 @@ func (d dClient) Get(name string) (*extensions.DaemonSet, error) {
|
||||
},
|
||||
}
|
||||
|
||||
if name == CorrectDaemonsetNamespace {
|
||||
ds.ObjectMeta.Namespace = CorrectDaemonset
|
||||
} else if name == IncorrectDaemonsetNamespace {
|
||||
return nil, fmt.Errorf("Mock daemonset didnt work")
|
||||
}
|
||||
|
||||
return ds, nil
|
||||
}
|
||||
func (d dClient) Create(ds *extensions.DaemonSet) (*extensions.DaemonSet, error) {
|
||||
|
@ -17,12 +17,15 @@ type pClient struct {
|
||||
}
|
||||
|
||||
const (
|
||||
PodNotPresent = "NOT_PRESENT"
|
||||
PodEmptyContainerStatuses = "EMPTY_CONTAINTER_STATUSES"
|
||||
PodEnvVariableValue = "podlist"
|
||||
PodNotPresent = "NOT_PRESENT"
|
||||
PodEnvVariableValue = "podlist"
|
||||
|
||||
IncorrectMatchLabel = "INCORRECT"
|
||||
NotReadyMatchLabel = "INCORRECT"
|
||||
|
||||
CorrectDaemonsetNamespace = "CORRECT_DAEMONSET_NAMESPACE"
|
||||
IncorrectDaemonsetNamespace = "INCORRECT_DAEMONSET_NAMESPACE"
|
||||
CorrectDaemonset = "CORRECT_DAEMONSET"
|
||||
)
|
||||
|
||||
func (p pClient) Get(name string) (*v1.Pod, error) {
|
||||
|
62
util/env/env.go
vendored
62
util/env/env.go
vendored
@ -3,18 +3,70 @@ package env
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/stackanetes/kubernetes-entrypoint/logger"
|
||||
)
|
||||
|
||||
func SplitEnvToList(env string, s ...string) (envList []string) {
|
||||
separator := ","
|
||||
if len(s) > 0 {
|
||||
separator = s[0]
|
||||
const (
|
||||
Separator = ":"
|
||||
)
|
||||
|
||||
type Dependency struct {
|
||||
Name string
|
||||
Namespace string
|
||||
}
|
||||
|
||||
func SplitCommand() []string {
|
||||
command := os.Getenv("COMMAND")
|
||||
if command == "" {
|
||||
return []string{}
|
||||
}
|
||||
commandList := strings.Split(command, " ")
|
||||
return commandList
|
||||
}
|
||||
|
||||
//SplitEnvToDeps returns list of namespaces and names pairs
|
||||
func SplitEnvToDeps(env string) (envList []Dependency) {
|
||||
separator := ","
|
||||
|
||||
e := os.Getenv(env)
|
||||
if e == "" {
|
||||
return envList
|
||||
}
|
||||
|
||||
envList = strings.Split(e, separator)
|
||||
envVars := strings.Split(e, separator)
|
||||
namespace := GetBaseNamespace()
|
||||
dep := Dependency{}
|
||||
for _, envVar := range envVars {
|
||||
if strings.Contains(envVar, Separator) {
|
||||
nameAfterSplit := strings.Split(envVar, Separator)
|
||||
if len(nameAfterSplit) != 2 {
|
||||
logger.Warning.Printf("Invalid format got %s, expected namespace:name", envVar)
|
||||
continue
|
||||
}
|
||||
if nameAfterSplit[0] == "" {
|
||||
logger.Warning.Printf("Invalid format, missing namespace", envVar)
|
||||
continue
|
||||
}
|
||||
|
||||
dep = Dependency{Name: nameAfterSplit[1], Namespace: nameAfterSplit[0]}
|
||||
|
||||
} else {
|
||||
dep = Dependency{Name: envVar, Namespace: namespace}
|
||||
}
|
||||
|
||||
envList = append(envList, dep)
|
||||
|
||||
}
|
||||
|
||||
return envList
|
||||
}
|
||||
|
||||
//GetBaseNamespace returns default namespace when user set empty one
|
||||
func GetBaseNamespace() string {
|
||||
namespace := os.Getenv("NAMESPACE")
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
return namespace
|
||||
}
|
||||
|
128
util/env/env_test.go
vendored
128
util/env/env_test.go
vendored
@ -6,72 +6,136 @@ import (
|
||||
)
|
||||
|
||||
func TestSplitEnvToListWithColon(t *testing.T) {
|
||||
|
||||
defer os.Unsetenv("TEST_LIST")
|
||||
|
||||
os.Setenv("TEST_LIST", "foo,bar")
|
||||
list := SplitEnvToList("TEST_LIST")
|
||||
list := SplitEnvToDeps("TEST_LIST")
|
||||
if list == nil {
|
||||
t.Errorf("Expected: not nil")
|
||||
}
|
||||
if list[0] != "foo" {
|
||||
if list[0].Name != "foo" {
|
||||
t.Errorf("Expected: foo got %s", list[0])
|
||||
}
|
||||
if list[1] != "bar" {
|
||||
if list[1].Name != "bar" {
|
||||
t.Errorf("Expected: bar got %s", list[1])
|
||||
}
|
||||
|
||||
os.Setenv("TEST_LIST", "foo1")
|
||||
list1 := SplitEnvToList("TEST_LIST")
|
||||
list1 := SplitEnvToDeps("TEST_LIST")
|
||||
if list1 == nil {
|
||||
t.Errorf("Expected: not nil")
|
||||
}
|
||||
if len(list1) != 1 {
|
||||
t.Errorf("Expected len to be 1 not %i", len(list1))
|
||||
}
|
||||
if list1[0] != "foo1" {
|
||||
if list1[0].Name != "foo1" {
|
||||
t.Errorf("Expected: foo1 got %s", list1[0])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSplitEnvToListWithSpace(t *testing.T) {
|
||||
os.Setenv("TEST_LIST", "foo bar")
|
||||
list := SplitEnvToList("TEST_LIST", " ")
|
||||
if list == nil {
|
||||
t.Errorf("Expected: not nil")
|
||||
os.Setenv("TEST_LIST", "foo:foo")
|
||||
list2 := SplitEnvToDeps("TEST_LIST")
|
||||
if list2[0].Name != "foo" {
|
||||
t.Errorf("Expected: foo got %s", list2[0].Name)
|
||||
}
|
||||
if list[0] != "foo" {
|
||||
t.Errorf("Expected: foo got %s", list[0])
|
||||
}
|
||||
if list[1] != "bar" {
|
||||
t.Errorf("Expected: bar got %s", list[1])
|
||||
if list2[0].Namespace != "foo" {
|
||||
t.Errorf("Expected: foo got %s", list2[0].Namespace)
|
||||
}
|
||||
|
||||
os.Setenv("TEST_LIST", "foo1")
|
||||
list1 := SplitEnvToList("TEST_LIST", " ")
|
||||
if list1 == nil {
|
||||
t.Errorf("Expected: not nil")
|
||||
os.Setenv("TEST_LIST", "bar")
|
||||
list3 := SplitEnvToDeps("TEST_LIST")
|
||||
if list3[0].Name != "bar" {
|
||||
t.Errorf("Expected: bar got %s", list3[0].Name)
|
||||
}
|
||||
if len(list1) != 1 {
|
||||
t.Errorf("Expected len to be 1 not %i", len(list1))
|
||||
}
|
||||
if list1[0] != "foo1" {
|
||||
t.Errorf("Expected: foo1 got %s", list1[0])
|
||||
if list3[0].Namespace != "default" {
|
||||
t.Errorf("Expected: default got %s", list3[0].Namespace)
|
||||
}
|
||||
|
||||
os.Setenv("TEST_LIST", "foo:foo1:foo2")
|
||||
list4 := SplitEnvToDeps("TEST_LIST")
|
||||
if len(list4) != 0 {
|
||||
t.Errorf("Expected list to be empty")
|
||||
}
|
||||
|
||||
os.Setenv("TEST_LIST", "foo:foo1:foo2,bar")
|
||||
list5 := SplitEnvToDeps("TEST_LIST")
|
||||
if list5[0].Namespace != "default" {
|
||||
t.Errorf("Expected: default got %s", list5[0].Namespace)
|
||||
}
|
||||
if list5[0].Name != "bar" {
|
||||
t.Errorf("Expected: bar got %s", list5[0].Name)
|
||||
}
|
||||
|
||||
os.Setenv("TEST_LIST", "foo:foo1:foo2,bar:foo")
|
||||
list6 := SplitEnvToDeps("TEST_LIST")
|
||||
if list6[0].Namespace != "bar" {
|
||||
t.Errorf("Expected: bar got %s", list6[0].Namespace)
|
||||
}
|
||||
if list6[0].Name != "foo" {
|
||||
t.Errorf("Expected: foo got %s", list6[0].Name)
|
||||
}
|
||||
|
||||
os.Setenv("TEST_LIST", ":foo")
|
||||
list7 := SplitEnvToDeps("TEST_LIST")
|
||||
if len(list7) != 0 {
|
||||
t.Errorf("Invalid format, missing namespace in pod")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitEmptyEnvWithColon(t *testing.T) {
|
||||
defer os.Unsetenv("TEST_LIST")
|
||||
os.Setenv("TEST_LIST", "")
|
||||
list := SplitEnvToList("TEST_LIST")
|
||||
list := SplitEnvToDeps("TEST_LIST")
|
||||
if list != nil {
|
||||
t.Errorf("Expected nil got %v", list)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitEmptyEnvWithSpace(t *testing.T) {
|
||||
os.Setenv("TEST_LIST", "")
|
||||
list := SplitEnvToList("TEST_LIST", " ")
|
||||
if list != nil {
|
||||
t.Errorf("Expected nil got %v", list)
|
||||
func TestSplitCommand(t *testing.T) {
|
||||
defer os.Unsetenv("COMMAND")
|
||||
list2 := SplitCommand()
|
||||
if len(list2) > 0 {
|
||||
t.Errorf("Expected len to be 0, got %v", len(list2))
|
||||
}
|
||||
os.Setenv("COMMAND", "echo test")
|
||||
list := SplitCommand()
|
||||
if list == nil {
|
||||
t.Errorf("Expected slice, got nil")
|
||||
return
|
||||
}
|
||||
if len(list) != 2 {
|
||||
t.Errorf("Expected two elements, got %v", len(list))
|
||||
}
|
||||
if list[0] != "echo" {
|
||||
t.Errorf("Expected echo, got %s", list[0])
|
||||
}
|
||||
if list[1] != "test" {
|
||||
t.Errorf("Expected test, got %s", list[1])
|
||||
}
|
||||
|
||||
os.Setenv("COMMAND", "")
|
||||
list1 := SplitCommand()
|
||||
if len(list1) > 0 {
|
||||
t.Errorf("Expected len to be 0, got %v", len(list1))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetBaseNamespace(t *testing.T) {
|
||||
defer os.Unsetenv("NAMESPACE")
|
||||
os.Setenv("NAMESPACE", "")
|
||||
getBaseNamespace := GetBaseNamespace()
|
||||
if getBaseNamespace != "default" {
|
||||
t.Errorf("Expected namespace to be default, got %v", getBaseNamespace)
|
||||
}
|
||||
os.Setenv("NAMESPACE", "foo")
|
||||
getBaseNamespace = GetBaseNamespace()
|
||||
if getBaseNamespace != "foo" {
|
||||
t.Errorf("Expected namespace to be foo, got %v", getBaseNamespace)
|
||||
}
|
||||
os.Setenv("NAMESPACE", "default")
|
||||
getBaseNamespace = GetBaseNamespace()
|
||||
if getBaseNamespace != "default" {
|
||||
t.Errorf("Expected namespace to be default, got %v", getBaseNamespace)
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stackanetes/kubernetes-entrypoint/util/env"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
@ -25,3 +26,11 @@ func GetIp() (ip string, err error) {
|
||||
ip = strings.Split(address[0].String(), "/")[0]
|
||||
return
|
||||
}
|
||||
|
||||
func ContainsSeparator(envString string, kind string) bool {
|
||||
if strings.Contains(envString, env.Separator) {
|
||||
fmt.Errorf("%s doesn't accept namespace: %s", kind, envString)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
13
util/util_suite_test.go
Normal file
13
util/util_suite_test.go
Normal file
@ -0,0 +1,13 @@
|
||||
package util_test
|
||||
|
||||
import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUtil(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Util Suite")
|
||||
}
|
16
util/util_test.go
Normal file
16
util/util_test.go
Normal file
@ -0,0 +1,16 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
const failingNamespaceUtil = "foo:util"
|
||||
|
||||
var _ = Describe("Util", func() {
|
||||
|
||||
It("fails on trying to resolve a socket with namespace", func() {
|
||||
contains := ContainsSeparator(failingNamespaceUtil, "Util")
|
||||
Expect(contains).To(Equal(true))
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user