Skip to content

Commit

Permalink
Inject env vars via webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
edeNFed committed Oct 26, 2024
1 parent 5ffff7e commit 4a8ed5c
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 37 deletions.
4 changes: 3 additions & 1 deletion instrumentor/controllers/instrumentationdevice/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ func SetupWithManager(mgr ctrl.Manager) error {
err = builder.
WebhookManagedBy(mgr).
For(&corev1.Pod{}).
WithDefaulter(&PodsWebhook{}).
WithDefaulter(&PodsWebhook{
Client: mgr.GetClient(),
}).
Complete()
if err != nil {
return err
Expand Down
80 changes: 45 additions & 35 deletions instrumentor/controllers/instrumentationdevice/pods_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import (
"fmt"
"strings"

"sigs.k8s.io/controller-runtime/pkg/log"

"github.com/odigos-io/odigos/k8sutils/pkg/workload"
"sigs.k8s.io/controller-runtime/pkg/client"

common "github.com/odigos-io/odigos/common"
"sigs.k8s.io/controller-runtime/pkg/webhook"

Expand All @@ -18,11 +23,14 @@ const (
EnvVarPodName = "ODIGOS_POD_NAME"
)

type PodsWebhook struct{}
type PodsWebhook struct {
Client client.Client
}

var _ webhook.CustomDefaulter = &PodsWebhook{}

func (p *PodsWebhook) Default(ctx context.Context, obj runtime.Object) error {
logger := log.FromContext(ctx)
pod, ok := obj.(*corev1.Pod)
if !ok {
return fmt.Errorf("expected a Pod but got a %T", obj)
Expand All @@ -32,31 +40,27 @@ func (p *PodsWebhook) Default(ctx context.Context, obj runtime.Object) error {
pod.Annotations = map[string]string{}
}

instApp, err := workload.GetRuntimeDetailsForPod(ctx, p.Client, pod)
if err != nil {
logger.Error(err, "Failed to get runtime details for pod")
return err
}

// Inject ODIGOS environment variables into all containers
injectOdigosEnvVars(pod)
p.injectOdigosEnvVars(pod)

return nil
}

func injectOdigosEnvVars(pod *corev1.Pod) {
namespace := pod.Namespace

// Common environment variables that do not change across containers
commonEnvVars := []corev1.EnvVar{
{
Name: EnvVarNamespace,
Value: namespace,
},
{
Name: EnvVarPodName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
},
func (p *PodsWebhook) envVarsToMap(envVars []corev1.EnvVar) map[string]corev1.EnvVar {
envMap := make(map[string]corev1.EnvVar)
for i := range envVars {
envMap[envVars[i].Name] = envVars[i]
}
return envMap
}

func (p *PodsWebhook) injectOdigosEnvVars(pod *corev1.Pod) {
for i := range pod.Spec.Containers {
container := &pod.Spec.Containers[i]

Expand All @@ -65,30 +69,36 @@ func injectOdigosEnvVars(pod *corev1.Pod) {
continue
}

// Check if the environment variables are already present, if so skip inject them again.
if envVarsExist(container.Env, commonEnvVars) {
continue
envsMap := p.envVarsToMap(container.Env)
envsMap[EnvVarNamespace] = corev1.EnvVar{
Name: EnvVarNamespace,
Value: pod.Namespace,
}

container.Env = append(container.Env, append(commonEnvVars, corev1.EnvVar{
envsMap[EnvVarPodName] = corev1.EnvVar{
Name: EnvVarPodName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
}

envsMap[EnvVarContainerName] = corev1.EnvVar{
Name: EnvVarContainerName,
Value: container.Name,
})...)
}

p.persistEnvVars(envsMap, container)
}
}

func envVarsExist(containerEnv []corev1.EnvVar, commonEnvVars []corev1.EnvVar) bool {
envMap := make(map[string]struct{})
for _, envVar := range containerEnv {
envMap[envVar.Name] = struct{}{} // Inserting empty struct as value
func (p *PodsWebhook) persistEnvVars(envsMap map[string]corev1.EnvVar, container *corev1.Container) {
envs := make([]corev1.EnvVar, 0, len(envsMap))
for _, env := range envsMap {
envs = append(envs, env)
}

for _, commonEnvVar := range commonEnvVars {
if _, exists := envMap[commonEnvVar.Name]; exists { // Checking if key exists
return true
}
}
return false
container.Env = envs
}

// Helper function to check if a container's resource limits have a key starting with the specified namespace
Expand Down
1 change: 0 additions & 1 deletion k8sutils/pkg/workload/ownerreference.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
// GetWorkloadFromOwnerReference retrieves both the workload name and workload kind
// from the provided owner reference.
func GetWorkloadFromOwnerReference(ownerReference metav1.OwnerReference) (workloadName string, workloadKind WorkloadKind, err error) {

return GetWorkloadNameAndKind(ownerReference.Name, ownerReference.Kind)
}

Expand Down
34 changes: 34 additions & 0 deletions k8sutils/pkg/workload/runtimeobjects.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package workload

import (
"context"
"errors"
"strings"

odigosv1 "github.com/odigos-io/odigos/api/odigos/v1alpha1"

Check failure on line 8 in k8sutils/pkg/workload/runtimeobjects.go

View workflow job for this annotation

GitHub Actions / verify-api-crds

no such package located

corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// this file contains utils related to odigos workload runtime object names.
Expand Down Expand Up @@ -34,3 +40,31 @@ func ExtractWorkloadInfoFromRuntimeObjectName(runtimeObjectName string) (workloa

return
}

func GetRuntimeDetailsForPod(ctx context.Context, kubeClient client.Client, pod *corev1.Pod) (*odigosv1.InstrumentedApplication, error) {
var workloadName string
var workloadKind WorkloadKind
for _, owner := range pod.OwnerReferences {
wn, wk, err := GetWorkloadFromOwnerReference(owner)
if IgnoreErrorKindNotSupported(err) != nil {
return nil, err
}

workloadName = wn
workloadKind = wk
break
}

instrumentedApplicationName := CalculateWorkloadRuntimeObjectName(workloadName, workloadKind)

var runtimeDetails odigosv1.InstrumentedApplication
err := kubeClient.Get(ctx, client.ObjectKey{
Namespace: pod.Namespace,
Name: instrumentedApplicationName,
}, &runtimeDetails)
if err != nil {
return nil, err
}

return &runtimeDetails, nil
}

0 comments on commit 4a8ed5c

Please sign in to comment.