Skip to content

Commit

Permalink
Set empty workload kind/name on unknown owner (#1074)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismuellner authored Aug 22, 2022
1 parent d87b935 commit a755492
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 32 deletions.
1 change: 1 addition & 0 deletions src/config/enrichment_injection.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const (
EnrichmentInjectedEnv = "DATA_INGEST_INJECTED"
EnrichmentWorkloadKindEnv = "DT_WORKLOAD_KIND"
EnrichmentWorkloadNameEnv = "DT_WORKLOAD_NAME"
EnrichmentUnknownWorkload = "UNKNOWN"
)

var (
Expand Down
12 changes: 10 additions & 2 deletions src/standalone/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,11 @@ func (env *environment) addWorkloadKind() error {
if err != nil {
return err
}
env.WorkloadKind = workloadKind
if workloadKind == config.EnrichmentUnknownWorkload {
env.WorkloadKind = ""
} else {
env.WorkloadKind = workloadKind
}
return nil
}

Expand All @@ -254,7 +258,11 @@ func (env *environment) addWorkloadName() error {
if err != nil {
return err
}
env.WorkloadName = workloadName
if workloadName == config.EnrichmentUnknownWorkload {
env.WorkloadName = ""
} else {
env.WorkloadName = workloadName
}
return nil
}

Expand Down
32 changes: 27 additions & 5 deletions src/standalone/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestNewEnv(t *testing.T) {
assert.True(t, env.DataIngestInjected)
})
t.Run(`create new env for only data-ingest injection`, func(t *testing.T) {
resetEnv := prepDataIngestTestEnv(t)
resetEnv := prepDataIngestTestEnv(t, false)

env, err := newEnv()
resetEnv()
Expand Down Expand Up @@ -69,6 +69,22 @@ func TestNewEnv(t *testing.T) {
assert.False(t, env.OneAgentInjected)
assert.True(t, env.DataIngestInjected)
})
t.Run(`create new env for only data-ingest injection with unknown owner workload`, func(t *testing.T) {
resetEnv := prepDataIngestTestEnv(t, true)

env, err := newEnv()
resetEnv()

require.NoError(t, err)
require.NotNil(t, env)

assert.NotEmpty(t, env.K8ClusterID)
assert.Empty(t, env.WorkloadKind)
assert.Empty(t, env.WorkloadName)

assert.False(t, env.OneAgentInjected)
assert.True(t, env.DataIngestInjected)
})
t.Run(`create new env for only oneagent`, func(t *testing.T) {
resetEnv := prepOneAgentTestEnv(t)

Expand Down Expand Up @@ -101,7 +117,7 @@ func TestNewEnv(t *testing.T) {
}

func prepCombinedTestEnv(t *testing.T) func() {
resetDataIngestEnvs := prepDataIngestTestEnv(t)
resetDataIngestEnvs := prepDataIngestTestEnv(t, false)
resetOneAgentEnvs := prepOneAgentTestEnv(t)
return func() {
resetDataIngestEnvs()
Expand Down Expand Up @@ -150,15 +166,21 @@ func prepOneAgentTestEnv(t *testing.T) func() {
return resetTestEnv(envs)
}

func prepDataIngestTestEnv(t *testing.T) func() {
func prepDataIngestTestEnv(t *testing.T, isUnknownWorkload bool) func() {
envs := []string{
config.EnrichmentWorkloadKindEnv,
config.EnrichmentWorkloadNameEnv,
config.K8sClusterIDEnv,
}
for _, envvar := range envs {
err := os.Setenv(envvar, fmt.Sprintf("TEST_%s", envvar))
require.NoError(t, err)
if isUnknownWorkload &&
(envvar == config.EnrichmentWorkloadKindEnv || envvar == config.EnrichmentWorkloadNameEnv) {
err := os.Setenv(envvar, "UNKNOWN")
require.NoError(t, err)
} else {
err := os.Setenv(envvar, fmt.Sprintf("TEST_%s", envvar))
require.NoError(t, err)
}
}

// Mode Env
Expand Down
2 changes: 1 addition & 1 deletion src/standalone/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func TestNewRunner(t *testing.T) {
assert.Empty(t, runner.hostTenant)
})
t.Run(`create runner with only data-ingest injection`, func(t *testing.T) {
resetEnv := prepDataIngestTestEnv(t)
resetEnv := prepDataIngestTestEnv(t, false)
runner, err := NewRunner(fs)
resetEnv()

Expand Down
29 changes: 23 additions & 6 deletions src/webhook/mutation/pod_mutator/dataingest_mutation/workload.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dataingest_mutation
import (
"context"

"github.com/Dynatrace/dynatrace-operator/src/config"
dtwebhook "github.com/Dynatrace/dynatrace-operator/src/webhook"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
Expand All @@ -15,13 +16,20 @@ type workloadInfo struct {
kind string
}

func newWorkloadInfo(partialObjectMetadata *metav1.PartialObjectMetadata) *workloadInfo {
return &workloadInfo{
func newWorkloadInfo(partialObjectMetadata *metav1.PartialObjectMetadata) workloadInfo {
return workloadInfo{
name: partialObjectMetadata.ObjectMeta.Name,
kind: partialObjectMetadata.Kind,
}
}

func newUnknownWorkloadInfo() workloadInfo {
return workloadInfo{
name: config.EnrichmentUnknownWorkload,
kind: config.EnrichmentUnknownWorkload,
}
}

func (mutator *DataIngestPodMutator) retrieveWorkload(request *dtwebhook.MutationRequest) (*workloadInfo, error) {
workload, err := findRootOwnerOfPod(request.Context, mutator.metaClient, request.Pod, request.Namespace.Name)
if err != nil {
Expand Down Expand Up @@ -52,12 +60,21 @@ func findRootOwnerOfPod(ctx context.Context, clt client.Client, pod *corev1.Pod,

func findRootOwner(ctx context.Context, clt client.Client, partialObjectMetadata *metav1.PartialObjectMetadata) (workloadInfo, error) {
if len(partialObjectMetadata.ObjectMeta.OwnerReferences) == 0 {
return *newWorkloadInfo(partialObjectMetadata), nil
if partialObjectMetadata.ObjectMeta.Name == "" {
// pod is not created directly and does not have an owner reference set
return newUnknownWorkloadInfo(), nil
}
return newWorkloadInfo(partialObjectMetadata), nil
}

objectMetadata := partialObjectMetadata.ObjectMeta
for _, owner := range objectMetadata.OwnerReferences {
if owner.Controller != nil && *owner.Controller && isWellKnownWorkload(owner) {
if owner.Controller != nil && *owner.Controller {
if !isWellKnownWorkload(owner) {
// pod is created by workload of kind that is not well known
return newUnknownWorkloadInfo(), nil
}

ownerObjectMetadata := &metav1.PartialObjectMetadata{
TypeMeta: metav1.TypeMeta{
APIVersion: owner.APIVersion,
Expand All @@ -72,13 +89,13 @@ func findRootOwner(ctx context.Context, clt client.Client, partialObjectMetadata
"name", owner.Name,
"namespace", objectMetadata.Namespace,
)
return *newWorkloadInfo(partialObjectMetadata), err
return newWorkloadInfo(partialObjectMetadata), err
}

return findRootOwner(ctx, clt, ownerObjectMetadata)
}
}
return *newWorkloadInfo(partialObjectMetadata), nil
return newWorkloadInfo(partialObjectMetadata), nil
}

func isWellKnownWorkload(ownerRef metav1.OwnerReference) bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ func TestFindRootOwnerOfPod(t *testing.T) {

t.Run("should return Pod if owner references are empty", func(t *testing.T) {
pod := corev1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
OwnerReferences: []metav1.OwnerReference{},
Name: resourceName,
Expand All @@ -80,27 +83,45 @@ func TestFindRootOwnerOfPod(t *testing.T) {
workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName)
require.NoError(t, err)
assert.Equal(t, resourceName, workloadInfo.name)
assert.Equal(t, "", workloadInfo.kind)
assert.Equal(t, "Pod", workloadInfo.kind)
})
}

func TestFindRootOwner(t *testing.T) {
ctx := context.TODO()
clt := fake.NewClient()
metadata := metav1.PartialObjectMetadata{
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: testPodName,
},
}

workload, err := findRootOwner(ctx, clt, &metadata)
t.Run("should be empty if owner is not well known", func(t *testing.T) {
pod := corev1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: "unknown",
Kind: "unknown",
Name: "test",
Controller: address.Of(true),
},
},
Name: resourceName,
},
}
client := fake.NewClient(&pod)
workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName)
require.NoError(t, err)
assert.Equal(t, "UNKNOWN", workloadInfo.name)
assert.Equal(t, "UNKNOWN", workloadInfo.kind)
})

assert.NoError(t, err)
assert.Equal(t, "Pod", workload.kind)
assert.Equal(t, testPodName, workload.name)
t.Run("should be empty if owner is not set, but name is empty", func(t *testing.T) {
pod := corev1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
},
}
client := fake.NewClient(&pod)
workloadInfo, err := findRootOwnerOfPod(ctx, client, &pod, namespaceName)
require.NoError(t, err)
assert.Equal(t, "UNKNOWN", workloadInfo.name)
assert.Equal(t, "UNKNOWN", workloadInfo.kind)
})
}

func createTestWorkloadInfo() *workloadInfo {
Expand Down

0 comments on commit a755492

Please sign in to comment.