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 resource attributes to collector sidecar #832

Merged
merged 10 commits into from
Apr 28, 2022
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -164,6 +164,8 @@ spec:
EOF
```

When using sidecar mode the OpenTelemetry collector container will have the environment variable `OTEL_RESOURCE_ATTRIBUTES`set with Kubernetes resource attributes, ready to be consumed by the [resourcedetection](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/resourcedetectionprocessor) processor.

### OpenTelemetry auto-instrumentation injection

The operator can inject and configure OpenTelemetry auto-instrumentation libraries. Currently Java, NodeJS and Python are supported.
28 changes: 28 additions & 0 deletions pkg/constants/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package constants

const (
EnvOTELServiceName = "OTEL_SERVICE_NAME"
EnvOTELExporterOTLPEndpoint = "OTEL_EXPORTER_OTLP_ENDPOINT"
EnvOTELResourceAttrs = "OTEL_RESOURCE_ATTRIBUTES"
EnvOTELPropagators = "OTEL_PROPAGATORS"
EnvOTELTracesSampler = "OTEL_TRACES_SAMPLER"
EnvOTELTracesSamplerArg = "OTEL_TRACES_SAMPLER_ARG"

EnvPodName = "OTEL_RESOURCE_ATTRIBUTES_POD_NAME"
EnvPodUID = "OTEL_RESOURCE_ATTRIBUTES_POD_UID"
EnvNodeName = "OTEL_RESOURCE_ATTRIBUTES_NODE_NAME"
)
50 changes: 20 additions & 30 deletions pkg/instrumentation/sdk.go
Original file line number Diff line number Diff line change
@@ -31,22 +31,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1"
"github.com/open-telemetry/opentelemetry-operator/pkg/constants"
)

const (
volumeName = "opentelemetry-auto-instrumentation"
initContainerName = "opentelemetry-auto-instrumentation"

envOTELServiceName = "OTEL_SERVICE_NAME"
envOTELExporterOTLPEndpoint = "OTEL_EXPORTER_OTLP_ENDPOINT"
envOTELResourceAttrs = "OTEL_RESOURCE_ATTRIBUTES"
envOTELPropagators = "OTEL_PROPAGATORS"
envOTELTracesSampler = "OTEL_TRACES_SAMPLER"
envOTELTracesSamplerArg = "OTEL_TRACES_SAMPLER_ARG"

envPodName = "OTEL_RESOURCE_ATTRIBUTES_POD_NAME"
envPodUID = "OTEL_RESOURCE_ATTRIBUTES_POD_UID"
envNodeName = "OTEL_RESOURCE_ATTRIBUTES_NODE_NAME"
)

// inject a new sidecar container to the given pod, based on the given OpenTelemetryCollector.
@@ -101,18 +91,18 @@ func (i *sdkInjector) injectCommonEnvVar(otelinst v1alpha1.Instrumentation, pod
func (i *sdkInjector) injectCommonSDKConfig(ctx context.Context, otelinst v1alpha1.Instrumentation, ns corev1.Namespace, pod corev1.Pod) corev1.Pod {
container := &pod.Spec.Containers[0]
resourceMap := i.createResourceMap(ctx, otelinst, ns, pod)
idx := getIndexOfEnv(container.Env, envOTELServiceName)
idx := getIndexOfEnv(container.Env, constants.EnvOTELServiceName)
if idx == -1 {
container.Env = append(container.Env, corev1.EnvVar{
Name: envOTELServiceName,
Name: constants.EnvOTELServiceName,
Value: chooseServiceName(pod, resourceMap),
})
}
if otelinst.Spec.Exporter.Endpoint != "" {
idx = getIndexOfEnv(container.Env, envOTELExporterOTLPEndpoint)
idx = getIndexOfEnv(container.Env, constants.EnvOTELExporterOTLPEndpoint)
if idx == -1 {
container.Env = append(container.Env, corev1.EnvVar{
Name: envOTELExporterOTLPEndpoint,
Name: constants.EnvOTELExporterOTLPEndpoint,
Value: otelinst.Spec.Endpoint,
})
}
@@ -121,45 +111,45 @@ func (i *sdkInjector) injectCommonSDKConfig(ctx context.Context, otelinst v1alph
// Some attributes might be empty, we should get them via k8s downward API
if resourceMap[string(semconv.K8SPodNameKey)] == "" {
container.Env = append(container.Env, corev1.EnvVar{
Name: envPodName,
Name: constants.EnvPodName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
})
resourceMap[string(semconv.K8SPodNameKey)] = fmt.Sprintf("$(%s)", envPodName)
resourceMap[string(semconv.K8SPodNameKey)] = fmt.Sprintf("$(%s)", constants.EnvPodName)
}
if otelinst.Spec.Resource.AddK8sUIDAttributes {
if resourceMap[string(semconv.K8SPodUIDKey)] == "" {
container.Env = append(container.Env, corev1.EnvVar{
Name: envPodUID,
Name: constants.EnvPodUID,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.uid",
},
},
})
resourceMap[string(semconv.K8SPodUIDKey)] = fmt.Sprintf("$(%s)", envPodUID)
resourceMap[string(semconv.K8SPodUIDKey)] = fmt.Sprintf("$(%s)", constants.EnvPodUID)
}
}
if resourceMap[string(semconv.K8SNodeNameKey)] == "" {
container.Env = append(container.Env, corev1.EnvVar{
Name: envNodeName,
Name: constants.EnvNodeName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "spec.nodeName",
},
},
})
resourceMap[string(semconv.K8SNodeNameKey)] = fmt.Sprintf("$(%s)", envNodeName)
resourceMap[string(semconv.K8SNodeNameKey)] = fmt.Sprintf("$(%s)", constants.EnvNodeName)
}

idx = getIndexOfEnv(container.Env, envOTELResourceAttrs)
idx = getIndexOfEnv(container.Env, constants.EnvOTELResourceAttrs)
resStr := resourceMapToStr(resourceMap)
if idx == -1 {
container.Env = append(container.Env, corev1.EnvVar{
Name: envOTELResourceAttrs,
Name: constants.EnvOTELResourceAttrs,
Value: resStr,
})
} else {
@@ -169,27 +159,27 @@ func (i *sdkInjector) injectCommonSDKConfig(ctx context.Context, otelinst v1alph
container.Env[idx].Value += resStr
}

idx = getIndexOfEnv(container.Env, envOTELPropagators)
idx = getIndexOfEnv(container.Env, constants.EnvOTELPropagators)
if idx == -1 && len(otelinst.Spec.Propagators) > 0 {
propagators := *(*[]string)((unsafe.Pointer(&otelinst.Spec.Propagators)))
container.Env = append(container.Env, corev1.EnvVar{
Name: envOTELPropagators,
Name: constants.EnvOTELPropagators,
Value: strings.Join(propagators, ","),
})
}

idx = getIndexOfEnv(container.Env, envOTELTracesSampler)
idx = getIndexOfEnv(container.Env, constants.EnvOTELTracesSampler)
// configure sampler only if it is configured in the CR
if idx == -1 && otelinst.Spec.Sampler.Type != "" {
idxSamplerArg := getIndexOfEnv(container.Env, envOTELTracesSamplerArg)
idxSamplerArg := getIndexOfEnv(container.Env, constants.EnvOTELTracesSamplerArg)
if idxSamplerArg == -1 {
container.Env = append(container.Env, corev1.EnvVar{
Name: envOTELTracesSampler,
Name: constants.EnvOTELTracesSampler,
Value: string(otelinst.Spec.Sampler.Type),
})
if otelinst.Spec.Sampler.Argument != "" {
container.Env = append(container.Env, corev1.EnvVar{
Name: envOTELTracesSamplerArg,
Name: constants.EnvOTELTracesSamplerArg,
Value: otelinst.Spec.Sampler.Argument,
})
}
@@ -223,7 +213,7 @@ func chooseServiceName(pod corev1.Pod, resources map[string]string) string {
func (i *sdkInjector) createResourceMap(ctx context.Context, otelinst v1alpha1.Instrumentation, ns corev1.Namespace, pod corev1.Pod) map[string]string {
// get existing resources env var and parse it into a map
existingRes := map[string]bool{}
existingResourceEnvIdx := getIndexOfEnv(pod.Spec.Containers[0].Env, envOTELResourceAttrs)
existingResourceEnvIdx := getIndexOfEnv(pod.Spec.Containers[0].Env, constants.EnvOTELResourceAttrs)
if existingResourceEnvIdx > -1 {
existingResArr := strings.Split(pod.Spec.Containers[0].Env[existingResourceEnvIdx].Value, ",")
for _, kv := range existingResArr {
120 changes: 120 additions & 0 deletions pkg/sidecar/attributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package sidecar contains operations related to sidecar manipulation (Add, update, remove).
package sidecar

import (
"fmt"
"sort"
"strings"

"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"

"github.com/open-telemetry/opentelemetry-operator/pkg/constants"
)

const resourceAttributesEnvName = "OTEL_RESOURCE_ATTRIBUTES"

type podReferences struct {
replicaset *appsv1.ReplicaSet
deployment *appsv1.Deployment
}

// getResourceAttributesEnv returns a list of environment variables. The list contains OTEL_RESOURCE_ATTRIBUTES and additional environment variables that use Kubernetes downward API to read pod specification.
// see: https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/
func getResourceAttributesEnv(ns corev1.Namespace, podReferences podReferences) []corev1.EnvVar {

var envvars []corev1.EnvVar

attributes := map[attribute.Key]string{
semconv.K8SPodNameKey: fmt.Sprintf("$(%s)", constants.EnvPodName),
semconv.K8SPodUIDKey: fmt.Sprintf("$(%s)", constants.EnvPodUID),
semconv.K8SNodeNameKey: fmt.Sprintf("$(%s)", constants.EnvNodeName),
semconv.K8SNamespaceNameKey: ns.Name,
}

if podReferences.deployment != nil {
attributes[semconv.K8SDeploymentUIDKey] = string(podReferences.deployment.UID)
attributes[semconv.K8SDeploymentNameKey] = string(podReferences.deployment.Name)
}

if podReferences.replicaset != nil {
attributes[semconv.K8SReplicaSetUIDKey] = string(podReferences.replicaset.UID)
attributes[semconv.K8SReplicaSetNameKey] = string(podReferences.replicaset.Name)
}

envvars = append(envvars, corev1.EnvVar{
Name: constants.EnvPodName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
})

envvars = append(envvars, corev1.EnvVar{
Name: constants.EnvPodUID,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.uid",
},
},
})

envvars = append(envvars, corev1.EnvVar{
Name: constants.EnvNodeName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "spec.nodeName",
},
},
})

envvars = append(envvars, corev1.EnvVar{
Name: resourceAttributesEnvName,
Value: mapToValue(attributes),
})

return envvars
}

func mapToValue(attributesMap map[attribute.Key]string) string {
var parts []string

// Sort it to make it predictable
keys := make([]string, 0, len(attributesMap))
for k := range attributesMap {
keys = append(keys, string(k))
}
sort.Strings(keys)

for _, key := range keys {
parts = append(parts, fmt.Sprintf("%s=%s", key, attributesMap[attribute.Key(key)]))
}
return strings.Join(parts, ",")
}

// check if container doesn't have already the OTEL_RESOURCE_ATTRIBUTES, we don't want to override it if it's already specified.
func hasResourceAttributeEnvVar(envvars []corev1.EnvVar) bool {
for _, env := range envvars {
if env.Name == resourceAttributesEnvName {
return true
}
}
return false
}
189 changes: 189 additions & 0 deletions pkg/sidecar/attributes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sidecar

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
appv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/open-telemetry/opentelemetry-operator/pkg/constants"
)

func TestGetAttributesEnvNoPodReferences(t *testing.T) {
ns := corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "my-ns",
},
}
references := podReferences{}
envs := getResourceAttributesEnv(ns, references)

expectedEnv := []corev1.EnvVar{
{
Name: constants.EnvPodName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
},
{
Name: constants.EnvPodUID,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.uid",
},
},
},
{
Name: constants.EnvNodeName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "spec.nodeName",
},
},
},
{
Name: resourceAttributesEnvName,
Value: fmt.Sprintf("%s=my-ns,%s=$(%s),%s=$(%s),%s=$(%s)",
semconv.K8SNamespaceNameKey,
semconv.K8SNodeNameKey,
constants.EnvNodeName,
semconv.K8SPodNameKey,
constants.EnvPodName,
semconv.K8SPodUIDKey,
constants.EnvPodUID,
),
},
}

assert.Equal(t, expectedEnv, envs)
}

func TestGetAttributesEnvWithPodReferences(t *testing.T) {
ns := corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "my-ns",
},
}
references := podReferences{
deployment: &appv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "my-deployment",
UID: "uuid-dep",
},
},
replicaset: &appv1.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
Name: "my-replicaset",
UID: "uuid-replicaset",
},
},
}
envs := getResourceAttributesEnv(ns, references)

expectedEnv := []corev1.EnvVar{
{
Name: constants.EnvPodName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
},
{
Name: constants.EnvPodUID,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.uid",
},
},
},
{
Name: constants.EnvNodeName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "spec.nodeName",
},
},
},
{
Name: resourceAttributesEnvName,
Value: fmt.Sprintf("%s=my-deployment,%s=uuid-dep,%s=my-ns,%s=$(%s),%s=$(%s),%s=$(%s),%s=my-replicaset,%s=uuid-replicaset",
semconv.K8SDeploymentNameKey,
semconv.K8SDeploymentUIDKey,
semconv.K8SNamespaceNameKey,
semconv.K8SNodeNameKey,
constants.EnvNodeName,
semconv.K8SPodNameKey,
constants.EnvPodName,
semconv.K8SPodUIDKey,
constants.EnvPodUID,
semconv.K8SReplicaSetNameKey,
semconv.K8SReplicaSetUIDKey,
),
},
}

assert.Equal(t, expectedEnv, envs)
}

func TestHasResourceAttributeEnvVar(t *testing.T) {
for _, tt := range []struct {
desc string
expected bool
env []corev1.EnvVar
}{
{
"has-attributes", true, []corev1.EnvVar{
{
Name: resourceAttributesEnvName,
Value: fmt.Sprintf("%s=my-deployment,%s=uuid-dep,%s=my-ns,%s=$(%s),%s=$(%s),%s=$(%s),%s=my-replicaset,%s=uuid-replicaset",
semconv.K8SDeploymentNameKey,
semconv.K8SDeploymentUIDKey,
semconv.K8SNamespaceNameKey,
semconv.K8SNodeNameKey,
constants.EnvNodeName,
semconv.K8SPodNameKey,
constants.EnvPodName,
semconv.K8SPodUIDKey,
constants.EnvPodUID,
semconv.K8SReplicaSetNameKey,
semconv.K8SReplicaSetUIDKey,
),
},
},
},

{
"does-not-have-attributes", false, []corev1.EnvVar{
{
Name: "other_env",
Value: "other_value",
},
},
},
} {
t.Run(tt.desc, func(t *testing.T) {
assert.Equal(t, tt.expected, hasResourceAttributeEnvVar(tt.env))
})
}
}
5 changes: 4 additions & 1 deletion pkg/sidecar/pod.go
Original file line number Diff line number Diff line change
@@ -32,10 +32,13 @@ const (
)

// add a new sidecar container to the given pod, based on the given OpenTelemetryCollector.
func add(cfg config.Config, logger logr.Logger, otelcol v1alpha1.OpenTelemetryCollector, pod corev1.Pod) (corev1.Pod, error) {
func add(cfg config.Config, logger logr.Logger, otelcol v1alpha1.OpenTelemetryCollector, pod corev1.Pod, attributes []corev1.EnvVar) (corev1.Pod, error) {
// add the container
volumes := collector.Volumes(cfg, otelcol)
container := collector.Container(cfg, logger, otelcol)
if !hasResourceAttributeEnvVar(container.Env) {
container.Env = append(container.Env, attributes...)
}
pod.Spec.Containers = append(pod.Spec.Containers, container)
pod.Spec.Volumes = append(pod.Spec.Volumes, volumes...)

38 changes: 36 additions & 2 deletions pkg/sidecar/pod_test.go
Original file line number Diff line number Diff line change
@@ -49,7 +49,7 @@ func TestAddSidecarWhenNoSidecarExists(t *testing.T) {
cfg := config.New(config.WithCollectorImage("some-default-image"))

// test
changed, err := add(cfg, logger, otelcol, pod)
changed, err := add(cfg, logger, otelcol, pod, nil)

// verify
assert.NoError(t, err)
@@ -74,7 +74,7 @@ func TestAddSidecarWhenOneExistsAlready(t *testing.T) {
cfg := config.New(config.WithCollectorImage("some-default-image"))

// test
changed, err := add(cfg, logger, otelcol, pod)
changed, err := add(cfg, logger, otelcol, pod, nil)

// verify
assert.NoError(t, err)
@@ -145,3 +145,37 @@ func TestExistsIn(t *testing.T) {
})
}
}

func TestAddSidecarWithAditionalEnv(t *testing.T) {
// prepare
pod := corev1.Pod{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{Name: "my-app"},
},
},
}
otelcol := v1alpha1.OpenTelemetryCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "otelcol-sample",
Namespace: "some-app",
},
}
cfg := config.New(config.WithCollectorImage("some-default-image"))

extraEnv := corev1.EnvVar{
Name: "extraenv",
Value: "extravalue",
}

// test
changed, err := add(cfg, logger, otelcol, pod, []corev1.EnvVar{
extraEnv,
})

// verify
assert.NoError(t, err)
assert.Len(t, changed.Spec.Containers, 2)
assert.Contains(t, changed.Spec.Containers[1].Env, extraEnv)

}
56 changes: 54 additions & 2 deletions pkg/sidecar/podmutator.go
Original file line number Diff line number Diff line change
@@ -20,7 +20,9 @@ import (
"strings"

"github.com/go-logr/logr"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

@@ -68,7 +70,6 @@ func (p *sidecarPodMutator) Mutate(ctx context.Context, ns corev1.Namespace, pod
}

// from this point and on, a sidecar is wanted

// check whether there's a sidecar already -- return the same pod if that's the case.
if existsIn(pod) {
logger.V(1).Info("pod already has sidecar in it, skipping injection")
@@ -88,10 +89,15 @@ func (p *sidecarPodMutator) Mutate(ctx context.Context, ns corev1.Namespace, pod
return pod, err
}

// getting pod references, if any
references := p.podReferences(ctx, pod.OwnerReferences, ns)
attributes := getResourceAttributesEnv(ns, references)

// once it's been determined that a sidecar is desired, none exists yet, and we know which instance it should talk to,
// we should add the sidecar.
logger.V(1).Info("injecting sidecar into pod", "otelcol-namespace", otelcol.Namespace, "otelcol-name", otelcol.Name)
return add(p.config, p.logger, otelcol, pod)

return add(p.config, p.logger, otelcol, pod, attributes)
}

func (p *sidecarPodMutator) getCollectorInstance(ctx context.Context, ns corev1.Namespace, ann string) (v1alpha1.OpenTelemetryCollector, error) {
@@ -138,3 +144,49 @@ func (p *sidecarPodMutator) selectCollectorInstance(ctx context.Context, ns core
return sidecars[0], nil
}
}

func (p *sidecarPodMutator) podReferences(ctx context.Context, ownerReferences []metav1.OwnerReference, ns corev1.Namespace) podReferences {
references := &podReferences{}
replicaSet := p.getReplicaSetReference(ctx, ownerReferences, ns)
if replicaSet != nil {
references.replicaset = replicaSet
deployment := p.getDeploymentReference(ctx, replicaSet)
if deployment != nil {
references.deployment = deployment
}
}
return *references
}

func (p *sidecarPodMutator) getReplicaSetReference(ctx context.Context, ownerReferences []metav1.OwnerReference, ns corev1.Namespace) *appsv1.ReplicaSet {
replicaSetName := findOwnerReferenceKind(ownerReferences, "ReplicaSet")
if replicaSetName != "" {
replicaSet := &appsv1.ReplicaSet{}
err := p.client.Get(ctx, types.NamespacedName{Name: replicaSetName, Namespace: ns.Name}, replicaSet)
if err == nil {
return replicaSet
}
}
return nil
}

func (p *sidecarPodMutator) getDeploymentReference(ctx context.Context, replicaSet *appsv1.ReplicaSet) *appsv1.Deployment {
deploymentName := findOwnerReferenceKind(replicaSet.OwnerReferences, "Deployment")
if deploymentName != "" {
deployment := &appsv1.Deployment{}
err := p.client.Get(ctx, types.NamespacedName{Name: deploymentName, Namespace: replicaSet.Namespace}, deployment)
if err == nil {
return deployment
}
}
return nil
}

func findOwnerReferenceKind(references []metav1.OwnerReference, kind string) string {
for _, reference := range references {
if reference.Kind == kind {
return reference.Name
}
}
return ""
}
6 changes: 6 additions & 0 deletions tests/e2e/smoke-sidecar/01-assert.yaml
Original file line number Diff line number Diff line change
@@ -9,5 +9,11 @@ spec:
containers:
- name: myapp
- name: otc-container
env:
- name: POD_NAME
- name: OTEL_RESOURCE_ATTRIBUTES_POD_NAME
- name: OTEL_RESOURCE_ATTRIBUTES_POD_UID
- name: OTEL_RESOURCE_ATTRIBUTES_NODE_NAME
- name: OTEL_RESOURCE_ATTRIBUTES
status:
phase: Running