Skip to content

Commit

Permalink
Added changes to respect env variable set from envFrom configMaps (#2272
Browse files Browse the repository at this point in the history
)

* Added changes to respect env variable set from envFrom configMaps

Signed-off-by: hiteshwani29 <hiteshwani29@gmail.com>

* Added testcases

Signed-off-by: hiteshwani29 <hiteshwani29@gmail.com>

* Resolve typo

Signed-off-by: hiteshwani29 <hiteshwani29@gmail.com>

---------

Signed-off-by: hiteshwani29 <hiteshwani29@gmail.com>
  • Loading branch information
hiteshwani29 authored Aug 2, 2023
1 parent efe0d36 commit df40425
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 6 deletions.
4 changes: 3 additions & 1 deletion controllers/appsv1/deployment_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ func (d *deploymentInterceptor) Handle(ctx context.Context, req admission.Reques
span.AddEvent(msg)
}

dep = inject.Sidecar(jaeger, dep)
envConfigMaps := corev1.ConfigMapList{}
d.client.List(ctx, &envConfigMaps, client.InNamespace(dep.Namespace))
dep = inject.Sidecar(jaeger, dep, inject.WithEnvFromConfigMaps(inject.GetConfigMapsMatchedEnvFromInDeployment(*dep, envConfigMaps.Items)))
marshaledDeploy, err := json.Marshal(dep)
if err != nil {
return admission.Errored(http.StatusInternalServerError, tracing.HandleError(err, span))
Expand Down
56 changes: 51 additions & 5 deletions pkg/inject/sidecar.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,20 @@ const (
envVarHostIP = "HOST_IP"
)

type SidecarOptions struct {
EnvConfigMaps []corev1.ConfigMap
}

type Options func(f *SidecarOptions)

func WithEnvFromConfigMaps(configMaps []corev1.ConfigMap) Options {
return func(s *SidecarOptions) {
s.EnvConfigMaps = configMaps
}
}

// Sidecar adds a new container to the deployment, connecting to the given jaeger instance
func Sidecar(jaeger *v1.Jaeger, dep *appsv1.Deployment) *appsv1.Deployment {
func Sidecar(jaeger *v1.Jaeger, dep *appsv1.Deployment, opts ...Options) *appsv1.Deployment {
deployment.NewAgent(jaeger) // we need some initialization from that, but we don't actually need the agent's instance here
logFields := jaeger.Logger().WithValues("deployment", dep.Name)

Expand All @@ -57,7 +69,7 @@ func Sidecar(jaeger *v1.Jaeger, dep *appsv1.Deployment) *appsv1.Deployment {
logFields.V(-2).Info("deployment is assigned to a different Jaeger instance, skipping sidecar injection")
return dep
}
decorate(dep)
decorate(dep, opts...)
hasAgent, agentContainerIndex := HasJaegerAgent(dep)
logFields.V(-1).Info("injecting sidecar")
if hasAgent { // This is an update
Expand Down Expand Up @@ -337,7 +349,7 @@ func container(jaeger *v1.Jaeger, dep *appsv1.Deployment, agentIdx int) corev1.C
return containerDefinition
}

func decorate(dep *appsv1.Deployment) {
func decorate(dep *appsv1.Deployment, opts ...Options) {
app, found := dep.Spec.Template.Labels["app.kubernetes.io/instance"]
if !found {
app, found = dep.Spec.Template.Labels["app.kubernetes.io/name"]
Expand All @@ -353,14 +365,20 @@ func decorate(dep *appsv1.Deployment) {
} else {
app += ".default"
}

sideCarOpt := &SidecarOptions{}
for _, opt := range opts {
opt(sideCarOpt)
}

for i := 0; i < len(dep.Spec.Template.Spec.Containers); i++ {
if !hasEnv(envVarServiceName, dep.Spec.Template.Spec.Containers[i].Env) {
if !hasEnv(envVarServiceName, dep.Spec.Template.Spec.Containers[i].Env) && !haskeyInEnvFromConfigMaps(envVarServiceName, sideCarOpt.EnvConfigMaps) {
dep.Spec.Template.Spec.Containers[i].Env = append(dep.Spec.Template.Spec.Containers[i].Env, corev1.EnvVar{
Name: envVarServiceName,
Value: app,
})
}
if !hasEnv(envVarPropagation, dep.Spec.Template.Spec.Containers[i].Env) {
if !hasEnv(envVarPropagation, dep.Spec.Template.Spec.Containers[i].Env) && !haskeyInEnvFromConfigMaps(envVarPropagation, sideCarOpt.EnvConfigMaps) {
dep.Spec.Template.Spec.Containers[i].Env = append(dep.Spec.Template.Spec.Containers[i].Env, corev1.EnvVar{
Name: envVarPropagation,
Value: "jaeger,b3,w3c",
Expand All @@ -376,6 +394,16 @@ func decorate(dep *appsv1.Deployment) {
}
}

func haskeyInEnvFromConfigMaps(key string, configMaps []corev1.ConfigMap) bool {
found := false
for _, cm := range configMaps {
if _, ok := cm.Data[key]; ok {
found = true
}
}
return found
}

func hasEnv(name string, vars []corev1.EnvVar) bool {
for i := 0; i < len(vars); i++ {
if vars[i].Name == name {
Expand Down Expand Up @@ -485,3 +513,21 @@ func isContainerPortAvailable(port int32, dep *appsv1.Deployment) bool {
}
return true
}

// GetConfigMapsMatchedEnvFromInDeployment returns configMap which matches with configMapRef
func GetConfigMapsMatchedEnvFromInDeployment(dep appsv1.Deployment, configMaps []corev1.ConfigMap) []corev1.ConfigMap {
configMapSearchMap := make(map[string]corev1.ConfigMap)
for _, cm := range configMaps {
configMapSearchMap[cm.Name] = cm
}

matchedConfigMaps := []corev1.ConfigMap{}
for _, container := range dep.Spec.Template.Spec.Containers {
for _, envConfigMap := range container.EnvFrom {
if matchedCM, ok := configMapSearchMap[envConfigMap.ConfigMapRef.Name]; ok {
matchedConfigMaps = append(matchedConfigMaps, matchedCM)
}
}
}
return matchedConfigMaps
}
79 changes: 79 additions & 0 deletions pkg/inject/sidecar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,63 @@ func TestInjectSidecarWithEnvVarsOverridePropagation(t *testing.T) {
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envVarServiceName, Value: "testapp.default"})
}

func TestInjectSidecarWithEnvFromK8sAppName(t *testing.T) {
// prepare
jaeger := v1.NewJaeger(types.NamespacedName{Name: "my-instance"})
envFromconfigMaps := []corev1.ConfigMap{{
ObjectMeta: metav1.ObjectMeta{
Name: "test-config",
Namespace: "default",
},
Data: map[string]string{
envVarServiceName: "jaeger,b3,w3c",
envVarPropagation: "test-service",
},
}}
dep := depEnvFromConfigRef(map[string]string{}, map[string]string{
"app": "noapp",
"app.kubernetes.io/name": "testapp",
}, []corev1.EnvFromSource{{ConfigMapRef: &corev1.ConfigMapEnvSource{LocalObjectReference: corev1.LocalObjectReference{Name: "test-config"}}}})

// test
dep = Sidecar(jaeger, dep, WithEnvFromConfigMaps(envFromconfigMaps))

// verify
assert.Len(t, dep.Spec.Template.Spec.Containers, 2)
assert.Len(t, dep.Spec.Template.Spec.Containers[0].Env, 0)
assert.Len(t, dep.Spec.Template.Spec.Containers[0].EnvFrom, 1)
actualConfigName := dep.Spec.Template.Spec.Containers[0].EnvFrom[0].ConfigMapRef.Name
assert.Contains(t, "test-config", actualConfigName)
}

func TestInjectSidecarWithoutEnvFromK8sAppName(t *testing.T) {
// prepare
jaeger := v1.NewJaeger(types.NamespacedName{Name: "my-instance"})
envFromconfigMaps := []corev1.ConfigMap{{
ObjectMeta: metav1.ObjectMeta{
Name: "test-config",
Namespace: "default",
},
Data: map[string]string{
"USRNAME": "=XUSUDA",
"PASSWORD": "+S=KDKS",
},
}}
dep := depEnvFromConfigRef(map[string]string{}, map[string]string{
"app": "noapp",
"app.kubernetes.io/name": "testapp",
}, []corev1.EnvFromSource{{ConfigMapRef: &corev1.ConfigMapEnvSource{LocalObjectReference: corev1.LocalObjectReference{Name: "test-config"}}}})

// test
dep = Sidecar(jaeger, dep, WithEnvFromConfigMaps(envFromconfigMaps))

// verify
assert.Len(t, dep.Spec.Template.Spec.Containers, 2)
assert.Len(t, dep.Spec.Template.Spec.Containers[0].Env, 2)
assert.Len(t, dep.Spec.Template.Spec.Containers[0].EnvFrom, 1)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: envVarServiceName, Value: "testapp.default"})
}

func TestInjectSidecarWithVolumeMounts(t *testing.T) {
// prepare
jaeger := v1.NewJaeger(types.NamespacedName{Name: "my-instance"})
Expand Down Expand Up @@ -765,6 +822,28 @@ func dep(annotations map[string]string, labels map[string]string) *appsv1.Deploy
}
}

func depEnvFromConfigRef(annotations map[string]string, labels map[string]string, envFromConfigRef []corev1.EnvFromSource) *appsv1.Deployment {
return &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Annotations: annotations,
Labels: labels,
},
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: labels,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "only_container",
EnvFrom: envFromConfigRef,
}},
},
},
},
}
}

func depWithTwoContainers(annotations map[string]string, labels map[string]string) *appsv1.Deployment {
dep := dep(annotations, labels)
dep.Spec.Template.Spec.Containers[0].Name = "container_0"
Expand Down

0 comments on commit df40425

Please sign in to comment.