Skip to content

Commit

Permalink
Ensure MY_POD_NAME, MY_POD_NAMESPACE, and K8S_SERVICE_NAME envVar def…
Browse files Browse the repository at this point in the history
…ined first (#437)

* Ensure MY_POD_NAME, MY_POD_NAMESPACE, and K8S_SERVICE_NAME envVar defined first

- handle the rabbitmq container envVar list as a special case if it's overwritten by override
- we need to ensure that MY_POD_NAME, MY_POD_NAMESPACE, and K8S_SERVICE_NAME  are defined first so other envVars values can reference them

Co-authored-by: Michal Kuratczyk <mkuratczyk@pivotal.io>
  • Loading branch information
ChunyiLyu and mkuratczyk authored Nov 2, 2020
1 parent 2a553b2 commit d0298dc
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 0 deletions.
34 changes: 34 additions & 0 deletions internal/resource/statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,34 @@ func patchPodSpec(podSpec, podSpecOverride *corev1.PodSpec) (corev1.PodSpec, err
if err != nil {
return corev1.PodSpec{}, fmt.Errorf("error unmarshalling patched Stateful Set: %v", err)
}

// handle the rabbitmq container envVar list as a special case if it's overwritten
// we need to ensure that MY_POD_NAME, MY_POD_NAMESPACE and K8S_SERVICE_NAME are defined first so other envVars values can reference them
if rmqContainer := containerRabbitmq(podSpecOverride.Containers); rmqContainer.Env != nil {
sortEnvVar(patchedPodSpec.Containers[0].Env)
}

return patchedPodSpec, nil
}

// sortEnvVar ensures that 'MY_POD_NAME', 'MY_POD_NAMESPACE' and 'K8S_SERVICE_NAME' envVars are defined first in the list
// this is to enable other envVars to reference them as variables successfully
func sortEnvVar(envVar []corev1.EnvVar) {
for i, e := range envVar {
if e.Name == "MY_POD_NAME" {
envVar[0], envVar[i] = envVar[i], envVar[0]
continue
}
if e.Name == "MY_POD_NAMESPACE" {
envVar[1], envVar[i] = envVar[i], envVar[1]
continue
}
if e.Name == "K8S_SERVICE_NAME" {
envVar[2], envVar[i] = envVar[i], envVar[2]
}
}
}

func (builder *StatefulSetBuilder) podTemplateSpec(annotations, labels map[string]string) corev1.PodTemplateSpec {
//Init Container resources
cpuRequest := k8sresource.MustParse(initContainerCPU)
Expand Down Expand Up @@ -703,3 +728,12 @@ func mergeMap(base, override map[string]string) map[string]string {

return result
}

func containerRabbitmq(containers []corev1.Container) corev1.Container {
for _, container := range containers {
if container.Name == "rabbitmq" {
return container
}
}
return corev1.Container{}
}
110 changes: 110 additions & 0 deletions internal/resource/statefulset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,116 @@ var _ = Describe("StatefulSet", func() {
},
))
})
Context("Container EnvVar", func() {
It("Overrides the envVar list while making sure that 'MY_POD_NAME', 'MY_POD_NAMESPACE' and 'K8S_SERVICE_NAME' are always defined first", func() {
instance.Spec.Override.StatefulSet = &rabbitmqv1beta1.StatefulSet{
Spec: &rabbitmqv1beta1.StatefulSetSpec{
Template: &rabbitmqv1beta1.PodTemplateSpec{
Spec: &corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "rabbitmq",
Env: []corev1.EnvVar{
{
Name: "test1",
Value: "test1",
},
{
Name: "RABBITMQ_USE_LONGNAME",
Value: "false",
},
{
Name: "RABBITMQ_STREAM_ADVERTISED_HOST",
Value: "$(MY_POD_NAME).$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE)",
},
},
},
},
},
},
},
}

builder = &resource.RabbitmqResourceBuilder{
Instance: &instance,
Scheme: scheme,
}
stsBuilder := builder.StatefulSet()
Expect(stsBuilder.Update(statefulSet)).To(Succeed())
Expect(extractContainer(statefulSet.Spec.Template.Spec.Containers, "rabbitmq").Env[0]).To(Equal(
corev1.EnvVar{
Name: "MY_POD_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
APIVersion: "v1",
},
},
}))
Expect(extractContainer(statefulSet.Spec.Template.Spec.Containers, "rabbitmq").Env[1]).To(Equal(
corev1.EnvVar{
Name: "MY_POD_NAMESPACE",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.namespace",
APIVersion: "v1",
},
},
}))
Expect(extractContainer(statefulSet.Spec.Template.Spec.Containers, "rabbitmq").Env[2]).To(Equal(
corev1.EnvVar{
Name: "K8S_SERVICE_NAME",
Value: "foo-rabbitmq-headless",
}))
Expect(extractContainer(statefulSet.Spec.Template.Spec.Containers, "rabbitmq").Env).To(ConsistOf(
corev1.EnvVar{
Name: "MY_POD_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
APIVersion: "v1",
},
},
},
corev1.EnvVar{
Name: "MY_POD_NAMESPACE",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.namespace",
APIVersion: "v1",
},
},
},
corev1.EnvVar{
Name: "test1",
Value: "test1",
},
corev1.EnvVar{
Name: "K8S_SERVICE_NAME",
Value: instance.ChildResourceName("headless"),
},
corev1.EnvVar{
Name: "RABBITMQ_USE_LONGNAME",
Value: "false",
},
corev1.EnvVar{
Name: "RABBITMQ_ENABLED_PLUGINS_FILE",
Value: "/operator/enabled_plugins",
},
corev1.EnvVar{
Name: "RABBITMQ_NODENAME",
Value: "rabbit@$(MY_POD_NAME).$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE)",
},
corev1.EnvVar{
Name: "K8S_HOSTNAME_SUFFIX",
Value: ".$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE)",
},
corev1.EnvVar{
Name: "RABBITMQ_STREAM_ADVERTISED_HOST",
Value: "$(MY_POD_NAME).$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE)",
}))
})
})
})

It("ensures override takes precedence when same property is set both at the top level and at the override level", func() {
Expand Down

0 comments on commit d0298dc

Please sign in to comment.