Skip to content

Commit f2b33f7

Browse files
committed
add e2e test to ensure that k8s.pod.ip metadata is not added
Signed-off-by: ChrsMark <[email protected]>
1 parent 84e7e04 commit f2b33f7

File tree

9 files changed

+389
-2
lines changed

9 files changed

+389
-2
lines changed

processor/k8sattributesprocessor/e2e_test.go

Lines changed: 154 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const (
3232
equal = iota
3333
regex
3434
exist
35+
shouldnotexist
3536
testKubeConfig = "/tmp/kube-config-otelcol-e2e-testing"
3637
uidRe = "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"
3738
startTimeRe = "^\\\\d{4}-\\\\d{2}-\\\\d{2}T\\\\d{2}%3A\\\\d{2}%3A\\\\d{2}(?:%2E\\\\d+)?[A-Z]?(?:[+.-](?:08%3A\\\\d{2}|\\\\d{2}[A-Z]))?$"
@@ -722,6 +723,146 @@ func TestE2E_MixRBAC(t *testing.T) {
722723
}
723724
}
724725

726+
// Test with `filter::namespace` set and only role binding to collector's SA. We can't get node and namespace labels/annotations.
727+
// While `k8s.pod.ip` is not set in `k8sattributes:extract:metadata` and the `pod_association` is not `connection`
728+
// we expect that the `k8s.pod.ip` metadata is not added.
729+
func TestE2E_NamespacedRBACNoPodIP(t *testing.T) {
730+
testDir := filepath.Join("testdata", "e2e", "namespacedrbacnopodip")
731+
732+
k8sClient, err := k8stest.NewK8sClient(testKubeConfig)
733+
require.NoError(t, err)
734+
735+
nsFile := filepath.Join(testDir, "namespace.yaml")
736+
buf, err := os.ReadFile(nsFile)
737+
require.NoErrorf(t, err, "failed to read namespace object file %s", nsFile)
738+
nsObj, err := k8stest.CreateObject(k8sClient, buf)
739+
require.NoErrorf(t, err, "failed to create k8s namespace from file %s", nsFile)
740+
nsName := nsObj.GetName()
741+
defer func() {
742+
require.NoErrorf(t, k8stest.DeleteObject(k8sClient, nsObj), "failed to delete namespace %s", nsName)
743+
}()
744+
745+
metricsConsumer := new(consumertest.MetricsSink)
746+
tracesConsumer := new(consumertest.TracesSink)
747+
logsConsumer := new(consumertest.LogsSink)
748+
shutdownSinks := startUpSinks(t, metricsConsumer, tracesConsumer, logsConsumer)
749+
defer shutdownSinks()
750+
751+
testID := uuid.NewString()[:8]
752+
collectorObjs := k8stest.CreateCollectorObjects(t, k8sClient, testID, filepath.Join(testDir, "collector"))
753+
createTeleOpts := &k8stest.TelemetrygenCreateOpts{
754+
ManifestsDir: filepath.Join(testDir, "telemetrygen"),
755+
TestID: testID,
756+
OtlpEndpoint: fmt.Sprintf("otelcol-%s.%s:4317", testID, nsName),
757+
DataTypes: []string{"metrics", "logs", "traces"},
758+
}
759+
telemetryGenObjs, telemetryGenObjInfos := k8stest.CreateTelemetryGenObjects(t, k8sClient, createTeleOpts)
760+
defer func() {
761+
for _, obj := range append(collectorObjs, telemetryGenObjs...) {
762+
require.NoErrorf(t, k8stest.DeleteObject(k8sClient, obj), "failed to delete object %s", obj.GetName())
763+
}
764+
}()
765+
766+
for _, info := range telemetryGenObjInfos {
767+
k8stest.WaitForTelemetryGenToStart(t, k8sClient, info.Namespace, info.PodLabelSelectors, info.Workload, info.DataType)
768+
}
769+
770+
wantEntries := 20 // Minimal number of metrics/traces/logs to wait for.
771+
waitForData(t, wantEntries, metricsConsumer, tracesConsumer, logsConsumer)
772+
773+
tcs := []struct {
774+
name string
775+
dataType component.DataType
776+
service string
777+
attrs map[string]*expectedValue
778+
}{
779+
{
780+
name: "traces-deployment",
781+
dataType: component.DataTypeTraces,
782+
service: "test-traces-deployment",
783+
attrs: map[string]*expectedValue{
784+
"k8s.pod.name": newExpectedValue(regex, "telemetrygen-"+testID+"-traces-deployment-[a-z0-9]*-[a-z0-9]*"),
785+
"k8s.pod.ip": newExpectedValue(shouldnotexist, ""),
786+
"k8s.pod.uid": newExpectedValue(regex, uidRe),
787+
"k8s.pod.start_time": newExpectedValue(exist, startTimeRe),
788+
"k8s.node.name": newExpectedValue(exist, ""),
789+
"k8s.namespace.name": newExpectedValue(equal, nsName),
790+
"k8s.deployment.name": newExpectedValue(equal, "telemetrygen-"+testID+"-traces-deployment"),
791+
"k8s.deployment.uid": newExpectedValue(regex, uidRe),
792+
"k8s.replicaset.name": newExpectedValue(regex, "telemetrygen-"+testID+"-traces-deployment-[a-z0-9]*"),
793+
"k8s.replicaset.uid": newExpectedValue(regex, uidRe),
794+
"k8s.annotations.workload": newExpectedValue(equal, "deployment"),
795+
"k8s.labels.app": newExpectedValue(equal, "telemetrygen-"+testID+"-traces-deployment"),
796+
"k8s.container.name": newExpectedValue(equal, "telemetrygen"),
797+
"container.image.name": newExpectedValue(equal, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen"),
798+
"container.image.tag": newExpectedValue(equal, "latest"),
799+
"container.id": newExpectedValue(exist, ""),
800+
},
801+
},
802+
{
803+
name: "metrics-deployment",
804+
dataType: component.DataTypeMetrics,
805+
service: "test-metrics-deployment",
806+
attrs: map[string]*expectedValue{
807+
"k8s.pod.name": newExpectedValue(regex, "telemetrygen-"+testID+"-metrics-deployment-[a-z0-9]*-[a-z0-9]*"),
808+
"k8s.pod.ip": newExpectedValue(shouldnotexist, ""),
809+
"k8s.pod.uid": newExpectedValue(regex, uidRe),
810+
"k8s.pod.start_time": newExpectedValue(exist, startTimeRe),
811+
"k8s.node.name": newExpectedValue(exist, ""),
812+
"k8s.namespace.name": newExpectedValue(equal, nsName),
813+
"k8s.deployment.name": newExpectedValue(equal, "telemetrygen-"+testID+"-metrics-deployment"),
814+
"k8s.deployment.uid": newExpectedValue(regex, uidRe),
815+
"k8s.replicaset.name": newExpectedValue(regex, "telemetrygen-"+testID+"-metrics-deployment-[a-z0-9]*"),
816+
"k8s.replicaset.uid": newExpectedValue(regex, uidRe),
817+
"k8s.annotations.workload": newExpectedValue(equal, "deployment"),
818+
"k8s.labels.app": newExpectedValue(equal, "telemetrygen-"+testID+"-metrics-deployment"),
819+
"k8s.container.name": newExpectedValue(equal, "telemetrygen"),
820+
"container.image.name": newExpectedValue(equal, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen"),
821+
"container.image.tag": newExpectedValue(equal, "latest"),
822+
"container.id": newExpectedValue(exist, ""),
823+
},
824+
},
825+
{
826+
name: "logs-deployment",
827+
dataType: component.DataTypeLogs,
828+
service: "test-logs-deployment",
829+
attrs: map[string]*expectedValue{
830+
"k8s.pod.name": newExpectedValue(regex, "telemetrygen-"+testID+"-logs-deployment-[a-z0-9]*-[a-z0-9]*"),
831+
"k8s.pod.ip": newExpectedValue(shouldnotexist, ""),
832+
"k8s.pod.uid": newExpectedValue(regex, uidRe),
833+
"k8s.pod.start_time": newExpectedValue(exist, startTimeRe),
834+
"k8s.node.name": newExpectedValue(exist, ""),
835+
"k8s.namespace.name": newExpectedValue(equal, nsName),
836+
"k8s.deployment.name": newExpectedValue(equal, "telemetrygen-"+testID+"-logs-deployment"),
837+
"k8s.deployment.uid": newExpectedValue(regex, uidRe),
838+
"k8s.replicaset.name": newExpectedValue(regex, "telemetrygen-"+testID+"-logs-deployment-[a-z0-9]*"),
839+
"k8s.replicaset.uid": newExpectedValue(regex, uidRe),
840+
"k8s.annotations.workload": newExpectedValue(equal, "deployment"),
841+
"k8s.labels.app": newExpectedValue(equal, "telemetrygen-"+testID+"-logs-deployment"),
842+
"k8s.container.name": newExpectedValue(equal, "telemetrygen"),
843+
"container.image.name": newExpectedValue(equal, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen"),
844+
"container.image.tag": newExpectedValue(equal, "latest"),
845+
"container.id": newExpectedValue(exist, ""),
846+
},
847+
},
848+
}
849+
850+
for _, tc := range tcs {
851+
t.Run(tc.name, func(t *testing.T) {
852+
switch tc.dataType {
853+
case component.DataTypeTraces:
854+
scanTracesForAttributes(t, tracesConsumer, tc.service, tc.attrs)
855+
case component.DataTypeMetrics:
856+
scanMetricsForAttributes(t, metricsConsumer, tc.service, tc.attrs)
857+
case component.DataTypeLogs:
858+
scanLogsForAttributes(t, logsConsumer, tc.service, tc.attrs)
859+
default:
860+
t.Fatalf("unknown data type %s", tc.dataType)
861+
}
862+
})
863+
}
864+
}
865+
725866
func scanTracesForAttributes(t *testing.T, ts *consumertest.TracesSink, expectedService string,
726867
kvs map[string]*expectedValue) {
727868
// Iterate over the received set of traces starting from the most recent entries due to a bug in the processor:
@@ -787,8 +928,12 @@ func scanLogsForAttributes(t *testing.T, ls *consumertest.LogsSink, expectedServ
787928

788929
func resourceHasAttributes(resource pcommon.Resource, kvs map[string]*expectedValue) error {
789930
foundAttrs := make(map[string]bool)
790-
for k := range kvs {
791-
foundAttrs[k] = false
931+
shouldNotFoundAttrs := make(map[string]bool)
932+
for k, v := range kvs {
933+
if v.mode != shouldnotexist {
934+
foundAttrs[k] = false
935+
}
936+
shouldNotFoundAttrs[k] = false
792937
}
793938

794939
resource.Attributes().Range(
@@ -806,6 +951,8 @@ func resourceHasAttributes(resource pcommon.Resource, kvs map[string]*expectedVa
806951
}
807952
case exist:
808953
foundAttrs[k] = true
954+
case shouldnotexist:
955+
shouldNotFoundAttrs[k] = true
809956
}
810957

811958
}
@@ -814,6 +961,11 @@ func resourceHasAttributes(resource pcommon.Resource, kvs map[string]*expectedVa
814961
)
815962

816963
var err error
964+
for k, v := range shouldNotFoundAttrs {
965+
if v {
966+
err = multierr.Append(err, fmt.Errorf("%v attribute should not be added", k))
967+
}
968+
}
817969
for k, v := range foundAttrs {
818970
if !v {
819971
err = multierr.Append(err, fmt.Errorf("%v attribute not found", k))
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: {{ .Name }}-config
5+
namespace: e2ek8sattribute-namespacedrbac
6+
data:
7+
relay: |
8+
exporters:
9+
otlp:
10+
endpoint: {{ .HostEndpoint }}:4317
11+
tls:
12+
insecure: true
13+
extensions:
14+
health_check: {}
15+
processors:
16+
k8sattributes:
17+
filter:
18+
namespace: e2ek8sattribute-namespacedrbac
19+
node_from_env_var: MY_NODE_NAME
20+
labels:
21+
- key: component
22+
value: telemetrygen
23+
op: equals
24+
fields:
25+
- key: spec.restartPolicy
26+
value: Never
27+
op: not-equals
28+
extract:
29+
annotations:
30+
- from: pod
31+
key: workload
32+
tag_name: k8s.annotations.workload
33+
labels:
34+
- from: pod
35+
key: app
36+
tag_name: k8s.labels.app
37+
metadata:
38+
- k8s.pod.name
39+
- k8s.pod.start_time
40+
- k8s.pod.uid
41+
- k8s.namespace.name
42+
- k8s.deployment.name
43+
- k8s.deployment.uid
44+
- k8s.replicaset.name
45+
- k8s.replicaset.uid
46+
- k8s.node.name
47+
- container.id
48+
- container.image.name
49+
- container.image.tag
50+
pod_association:
51+
- sources:
52+
- from: resource_attribute
53+
name: k8s.deployment.name
54+
receivers:
55+
otlp:
56+
protocols:
57+
grpc:
58+
endpoint: ${env:MY_POD_IP}:4317
59+
service:
60+
extensions:
61+
- health_check
62+
pipelines:
63+
metrics:
64+
exporters:
65+
- otlp
66+
processors:
67+
- k8sattributes
68+
receivers:
69+
- otlp
70+
traces:
71+
exporters:
72+
- otlp
73+
processors:
74+
- k8sattributes
75+
receivers:
76+
- otlp
77+
logs:
78+
exporters:
79+
- otlp
80+
processors:
81+
- k8sattributes
82+
receivers:
83+
- otlp
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: {{ .Name }}
5+
namespace: e2ek8sattribute-namespacedrbac
6+
spec:
7+
replicas: 1
8+
selector:
9+
matchLabels:
10+
app.kubernetes.io/name: opentelemetry-collector
11+
app.kubernetes.io/instance: {{ .Name }}
12+
template:
13+
metadata:
14+
labels:
15+
app.kubernetes.io/name: opentelemetry-collector
16+
app.kubernetes.io/instance: {{ .Name }}
17+
spec:
18+
serviceAccountName: {{ .Name }}
19+
containers:
20+
- name: opentelemetry-collector
21+
command:
22+
- /otelcontribcol
23+
- --config=/conf/relay.yaml
24+
image: "otelcontribcol:latest"
25+
imagePullPolicy: Never
26+
ports:
27+
- name: otlp
28+
containerPort: 4317
29+
protocol: TCP
30+
env:
31+
- name: MY_POD_IP
32+
valueFrom:
33+
fieldRef:
34+
apiVersion: v1
35+
fieldPath: status.podIP
36+
- name: MY_NODE_NAME
37+
valueFrom:
38+
fieldRef:
39+
apiVersion: v1
40+
fieldPath: spec.nodeName
41+
livenessProbe:
42+
httpGet:
43+
path: /
44+
port: 13133
45+
initialDelaySeconds: 3
46+
readinessProbe:
47+
httpGet:
48+
path: /
49+
port: 13133
50+
initialDelaySeconds: 3
51+
resources:
52+
limits:
53+
cpu: 128m
54+
memory: 256Mi
55+
volumeMounts:
56+
- mountPath: /conf
57+
name: opentelemetry-collector-configmap
58+
volumes:
59+
- name: opentelemetry-collector-configmap
60+
configMap:
61+
name: {{ .Name }}-config
62+
items:
63+
- key: relay
64+
path: relay.yaml
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: Role
3+
metadata:
4+
name: {{ .Name }}
5+
namespace: e2ek8sattribute-namespacedrbac
6+
rules:
7+
- apiGroups: [""]
8+
resources: ["pods"]
9+
verbs: ["get", "watch", "list"]
10+
- apiGroups: ["apps"]
11+
resources: ["replicasets"]
12+
verbs: ["get", "watch", "list"]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: RoleBinding
3+
metadata:
4+
name: {{ .Name }}
5+
namespace: e2ek8sattribute-namespacedrbac
6+
roleRef:
7+
apiGroup: rbac.authorization.k8s.io
8+
kind: Role
9+
name: {{ .Name }}
10+
subjects:
11+
- kind: ServiceAccount
12+
name: {{ .Name }}
13+
namespace: e2ek8sattribute-namespacedrbac
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: {{ .Name }}
5+
namespace: e2ek8sattribute-namespacedrbac
6+
spec:
7+
type: ClusterIP
8+
ports:
9+
- name: otlp
10+
port: 4317
11+
targetPort: 4317
12+
protocol: TCP
13+
appProtocol: grpc
14+
selector:
15+
app.kubernetes.io/name: opentelemetry-collector
16+
app.kubernetes.io/instance: {{ .Name }}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
apiVersion: v1
2+
kind: ServiceAccount
3+
metadata:
4+
name: {{ .Name }}
5+
namespace: e2ek8sattribute-namespacedrbac
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: e2ek8sattribute-namespacedrbac
5+
labels:
6+
foons: barns

0 commit comments

Comments
 (0)