Skip to content

Commit

Permalink
[processor/k8sattributes] Support name:tag@digest image name format
Browse files Browse the repository at this point in the history
  • Loading branch information
spiffyy99 committed Nov 2, 2024
1 parent 0dcdebf commit 90d3a08
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 25 deletions.
27 changes: 27 additions & 0 deletions .chloggen/fix-k8s-image-parsing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: bug_fix

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: processor/k8sattribute

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: fixes parsing of k8s image names to support images with tags and digests.

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [36131]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
34 changes: 25 additions & 9 deletions processor/k8sattributesprocessor/internal/kube/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package kube // import "github.com/open-telemetry/opentelemetry-collector-contri

import (
"context"
"errors"
"fmt"
"regexp"
"strings"
Expand Down Expand Up @@ -632,6 +633,23 @@ func removeUnnecessaryPodData(pod *api_v1.Pod, rules ExtractionRules) *api_v1.Po
return &transformedPod
}

// parseAttributesFromImage parses the image name and tag for differently-formatted image names.
func parseNameAndTagFromImage(image string) (name, tag string, err error) {
ref, err := reference.Parse(image)
if err != nil {
return
}
namedRef, ok := ref.(reference.Named)
if !ok {
return "", "", errors.New("cannot retrieve image name")
}
name = namedRef.Name()
if taggedRef, ok := namedRef.(reference.Tagged); ok {
tag = taggedRef.Tag()
}
return
}

func (c *WatchClient) extractPodContainersAttributes(pod *api_v1.Pod) PodContainers {
containers := PodContainers{
ByID: map[string]*Container{},
Expand All @@ -643,16 +661,14 @@ func (c *WatchClient) extractPodContainersAttributes(pod *api_v1.Pod) PodContain
if c.Rules.ContainerImageName || c.Rules.ContainerImageTag {
for _, spec := range append(pod.Spec.Containers, pod.Spec.InitContainers...) {
container := &Container{}
nameTagSep := strings.LastIndex(spec.Image, ":")
if c.Rules.ContainerImageName {
if nameTagSep > 0 {
container.ImageName = spec.Image[:nameTagSep]
} else {
container.ImageName = spec.Image
name, tag, err := parseNameAndTagFromImage(spec.Image)
if err != nil {
if c.Rules.ContainerImageName {
container.ImageName = name
}
if c.Rules.ContainerImageTag {
container.ImageTag = tag
}
}
if c.Rules.ContainerImageTag && nameTagSep > 0 {
container.ImageTag = spec.Image[nameTagSep+1:]
}
containers.ByName[spec.Name] = container
}
Expand Down
70 changes: 57 additions & 13 deletions processor/k8sattributesprocessor/internal/kube/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1469,11 +1469,15 @@ func Test_extractPodContainersAttributes(t *testing.T) {
Containers: []api_v1.Container{
{
Name: "container1",
Image: "test/image1:0.1.0",
Image: "example.com:5000/test/image1:0.1.0",
},
{
Name: "container2",
Image: "example.com:port1/image2:0.2.0",
Image: "example.com:81/image2@sha256:430ac608abaa332de4ce45d68534447c7a206edc5e98aaff9923ecc12f8a80d9",
},
{
Name: "container3",
Image: "example-website.com/image3:1.0@sha256:4b0b1b6f6cdd3e5b9e55f74a1e8d19ed93a3f5a04c6b6c3c57c4e6d19f6b7c4d",
},
},
InitContainers: []api_v1.Container{
Expand All @@ -1494,7 +1498,13 @@ func Test_extractPodContainersAttributes(t *testing.T) {
{
Name: "container2",
ContainerID: "docker://container2-id-456",
ImageID: "sha256:430ac608abaa332de4ce45d68534447c7a206edc5e98aaff9923ecc12f8a80d9",
ImageID: "sha256:4b0b1b6f6cdd3e5b9e55f74a1e8d19ed93a3f5a04c6b6c3c57c4e6d19f6b7c4d",
RestartCount: 2,
},
{
Name: "container3",
ContainerID: "docker://container3-id-abc",
ImageID: "docker.io/otel/collector:2.0.0@sha256:430ac608abaa332de4ce45d68534447c7a206edc5e98aaff9923ecc12f8a80d9",
RestartCount: 2,
},
},
Expand Down Expand Up @@ -1538,13 +1548,15 @@ func Test_extractPodContainersAttributes(t *testing.T) {
pod: &pod,
want: PodContainers{
ByID: map[string]*Container{
"container1-id-123": {ImageName: "test/image1"},
"container2-id-456": {ImageName: "example.com:port1/image2"},
"container1-id-123": {ImageName: "example.com:5000/test/image1"},
"container2-id-456": {ImageName: "example.com:81/image2"},
"container3-id-abc": {ImageName: "example-website.com/image3"},
"init-container-id-789": {ImageName: "test/init-image"},
},
ByName: map[string]*Container{
"container1": {ImageName: "test/image1"},
"container2": {ImageName: "example.com:port1/image2"},
"container1": {ImageName: "example.com:5000/test/image1"},
"container2": {ImageName: "example.com:81/image2"},
"container3": {ImageName: "example-website.com/image3"},
"init_container": {ImageName: "test/init-image"},
},
},
Expand Down Expand Up @@ -1589,6 +1601,11 @@ func Test_extractPodContainersAttributes(t *testing.T) {
2: {ContainerID: "container2-id-456"},
},
},
"container3-id-abc": {
Statuses: map[int]ContainerStatus{
2: {ContainerID: "container3-id-abc"},
},
},
"init-container-id-789": {
Statuses: map[int]ContainerStatus{
0: {ContainerID: "init-container-id-789"},
Expand All @@ -1606,6 +1623,11 @@ func Test_extractPodContainersAttributes(t *testing.T) {
2: {ContainerID: "container2-id-456"},
},
},
"container3": {
Statuses: map[int]ContainerStatus{
2: {ContainerID: "container3-id-abc"},
},
},
"init_container": {
Statuses: map[int]ContainerStatus{
0: {ContainerID: "init-container-id-789"},
Expand All @@ -1632,6 +1654,11 @@ func Test_extractPodContainersAttributes(t *testing.T) {
2: {},
},
},
"container3-id-abc": {
Statuses: map[int]ContainerStatus{
2: {ImageRepoDigest: "docker.io/otel/collector:2.0.0@sha256:430ac608abaa332de4ce45d68534447c7a206edc5e98aaff9923ecc12f8a80d9"},
},
},
"init-container-id-789": {
Statuses: map[int]ContainerStatus{
0: {ImageRepoDigest: "ghcr.io/initimage1@sha256:42e8ba40f9f70d604684c3a2a0ed321206b7e2e3509fdb2c8836d34f2edfb57b"},
Expand All @@ -1649,6 +1676,11 @@ func Test_extractPodContainersAttributes(t *testing.T) {
2: {},
},
},
"container3": {
Statuses: map[int]ContainerStatus{
2: {ImageRepoDigest: "docker.io/otel/collector:2.0.0@sha256:430ac608abaa332de4ce45d68534447c7a206edc5e98aaff9923ecc12f8a80d9"},
},
},
"init_container": {
Statuses: map[int]ContainerStatus{
0: {ImageRepoDigest: "ghcr.io/initimage1@sha256:42e8ba40f9f70d604684c3a2a0ed321206b7e2e3509fdb2c8836d34f2edfb57b"},
Expand All @@ -1669,19 +1701,25 @@ func Test_extractPodContainersAttributes(t *testing.T) {
want: PodContainers{
ByID: map[string]*Container{
"container1-id-123": {
ImageName: "test/image1",
ImageName: "example.com:5000/test/image1",
ImageTag: "0.1.0",
Statuses: map[int]ContainerStatus{
0: {ContainerID: "container1-id-123", ImageRepoDigest: "docker.io/otel/collector@sha256:55d008bc28344c3178645d40e7d07df30f9d90abe4b53c3fc4e5e9c0295533da"},
},
},
"container2-id-456": {
ImageName: "example.com:port1/image2",
ImageTag: "0.2.0",
ImageName: "example.com:81/image2",
Statuses: map[int]ContainerStatus{
2: {ContainerID: "container2-id-456"},
},
},
"container3-id-abc": {
ImageName: "example-website.com/image3",
ImageTag: "1.0",
Statuses: map[int]ContainerStatus{
2: {ContainerID: "container3-id-abc", ImageRepoDigest: "docker.io/otel/collector:2.0.0@sha256:430ac608abaa332de4ce45d68534447c7a206edc5e98aaff9923ecc12f8a80d9"},
},
},
"init-container-id-789": {
ImageName: "test/init-image",
ImageTag: "1.0.2",
Expand All @@ -1692,19 +1730,25 @@ func Test_extractPodContainersAttributes(t *testing.T) {
},
ByName: map[string]*Container{
"container1": {
ImageName: "test/image1",
ImageName: "example.com:5000/test/image1",
ImageTag: "0.1.0",
Statuses: map[int]ContainerStatus{
0: {ContainerID: "container1-id-123", ImageRepoDigest: "docker.io/otel/collector@sha256:55d008bc28344c3178645d40e7d07df30f9d90abe4b53c3fc4e5e9c0295533da"},
},
},
"container2": {
ImageName: "example.com:port1/image2",
ImageTag: "0.2.0",
ImageName: "example.com:81/image2",
Statuses: map[int]ContainerStatus{
2: {ContainerID: "container2-id-456"},
},
},
"container3": {
ImageName: "example-website.com/image3",
ImageTag: "1.0",
Statuses: map[int]ContainerStatus{
2: {ContainerID: "container3-id-abc", ImageRepoDigest: "docker.io/otel/collector:2.0.0@sha256:430ac608abaa332de4ce45d68534447c7a206edc5e98aaff9923ecc12f8a80d9"},
},
},
"init_container": {
ImageName: "test/init-image",
ImageTag: "1.0.2",
Expand Down
4 changes: 2 additions & 2 deletions processor/k8sattributesprocessor/processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,7 @@ func TestProcessorAddContainerAttributes(t *testing.T) {
ByName: map[string]*kube.Container{
"app": {
Statuses: map[int]kube.ContainerStatus{
2: {ImageRepoDigest: "docker.io/otel/collector@sha256:deadbeef02"},
2: {ImageRepoDigest: "docker.io/otel/collector:1.2.3@sha256:deadbeef02"},
},
},
},
Expand All @@ -1145,7 +1145,7 @@ func TestProcessorAddContainerAttributes(t *testing.T) {
wantAttrs: map[string]any{
kube.K8sIPLabelName: "1.1.1.1",
conventions.AttributeK8SContainerName: "app",
containerImageRepoDigests: []string{"docker.io/otel/collector@sha256:deadbeef02"},
containerImageRepoDigests: []string{"docker.io/otel/collector:1.2.3@sha256:deadbeef02"},
},
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ spec:
{{- if eq .DataType "traces" }}
- --status-code=
{{- end }}
image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest
image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest@sha256:430ac608abaa332de4ce45d68534447c7a206edc5e98aaff9923ecc12f8a80d9
imagePullPolicy: IfNotPresent
name: telemetrygen
restartPolicy: Always

0 comments on commit 90d3a08

Please sign in to comment.