Skip to content

Commit 78fc63e

Browse files
committed
Fix
Signed-off-by: Pavol Loffay <[email protected]>
1 parent 0dde4db commit 78fc63e

9 files changed

+571
-133
lines changed

apis/v1alpha1/instrumentation_types.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,16 @@ type Exporter struct {
108108

109109
// TLS defines TLS configuration for exporter.
110110
type TLS struct {
111-
// SecretName defines a secret name that will be used to configure TLS on the exporter.
111+
// SecretName defines secret name that will be used to configure TLS on the exporter.
112112
// It is user responsibility to create the secret in the namespace of the workload.
113113
// The secret should contain keys ca.crt, tls.key, tls.crt
114114
SecretName string `json:"secretName,omitempty"`
115-
// CA defines the key of certificate in the secret or absolute path to a certificate.
115+
116+
// ConfigMapName defines configmap name with CA certificate. If it is not defined CA certificate will be
117+
// used from the secret defined in SecretName.
118+
ConfigMapName string `json:"configMapName,omitempty"`
119+
120+
// CA defines the key of certificate in the configmap map, secret or absolute path to a certificate.
116121
// The absolute path can be used when certificate is already present on the workload filesystem e.g.
117122
// /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt
118123
CA string `json:"ca,omitempty"`

config/crd/bases/opentelemetry.io_instrumentations.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,8 @@ spec:
413413
type: string
414414
cert:
415415
type: string
416+
configMapName:
417+
type: string
416418
key:
417419
type: string
418420
secretName:

config/manager/kustomization.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
resources:
22
- manager.yaml
3+
apiVersion: kustomize.config.k8s.io/v1beta1
4+
kind: Kustomization
5+
images:
6+
- name: controller
7+
newName: docker.io/pavolloffay/opentelemetry-operator
8+
newTag: dev-0dde4db3-1728483172

pkg/instrumentation/exporter.go

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package instrumentation
16+
17+
import (
18+
"fmt"
19+
"github.com/open-telemetry/opentelemetry-operator/internal/naming"
20+
"path/filepath"
21+
22+
corev1 "k8s.io/api/core/v1"
23+
24+
"github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1"
25+
"github.com/open-telemetry/opentelemetry-operator/pkg/constants"
26+
)
27+
28+
func configureExporter(exporter v1alpha1.Exporter, pod *corev1.Pod, container *corev1.Container) {
29+
if exporter.Endpoint != "" {
30+
if getIndexOfEnv(container.Env, constants.EnvOTELExporterOTLPEndpoint) == -1 {
31+
container.Env = append(container.Env, corev1.EnvVar{
32+
Name: constants.EnvOTELExporterOTLPEndpoint,
33+
Value: exporter.Endpoint,
34+
})
35+
}
36+
}
37+
if exporter.TLS == nil {
38+
return
39+
}
40+
// the name cannot be longer than 63 characters
41+
secretVolumeName := naming.Truncate("%s-secret-%s", 63, volumeName, exporter.TLS.SecretName)
42+
secretMountPath := fmt.Sprintf("/otel-auto-instrumentation-secret-%s", exporter.TLS.SecretName)
43+
configMapVolumeName := naming.Truncate("%s-configmap-%s", 63, volumeName, exporter.TLS.ConfigMapName)
44+
configMapMountPath := fmt.Sprintf("/otel-auto-instrumentation-configmap-%s", exporter.TLS.ConfigMapName)
45+
46+
if exporter.TLS.CA != "" {
47+
mountPath := secretMountPath
48+
if exporter.TLS.ConfigMapName != "" {
49+
mountPath = configMapMountPath
50+
}
51+
envVarVal := fmt.Sprintf("%s/%s", mountPath, exporter.TLS.CA)
52+
if filepath.IsAbs(exporter.TLS.CA) {
53+
envVarVal = exporter.TLS.CA
54+
}
55+
if getIndexOfEnv(container.Env, constants.EnvOTELExporterCertificate) == -1 {
56+
container.Env = append(container.Env, corev1.EnvVar{
57+
Name: constants.EnvOTELExporterCertificate,
58+
Value: envVarVal,
59+
})
60+
}
61+
}
62+
if exporter.TLS.Cert != "" {
63+
envVarVal := fmt.Sprintf("%s/%s", secretMountPath, exporter.TLS.Cert)
64+
if filepath.IsAbs(exporter.TLS.Cert) {
65+
envVarVal = exporter.TLS.Cert
66+
}
67+
if getIndexOfEnv(container.Env, constants.EnvOTELExporterClientCertificate) == -1 {
68+
container.Env = append(container.Env, corev1.EnvVar{
69+
Name: constants.EnvOTELExporterClientCertificate,
70+
Value: envVarVal,
71+
})
72+
}
73+
}
74+
if exporter.TLS.Key != "" {
75+
envVarVar := fmt.Sprintf("%s/%s", secretMountPath, exporter.TLS.Key)
76+
if filepath.IsAbs(exporter.TLS.Key) {
77+
envVarVar = exporter.TLS.Key
78+
}
79+
if getIndexOfEnv(container.Env, constants.EnvOTELExporterClientKey) == -1 {
80+
container.Env = append(container.Env, corev1.EnvVar{
81+
Name: constants.EnvOTELExporterClientKey,
82+
Value: envVarVar,
83+
})
84+
}
85+
}
86+
87+
if exporter.TLS.SecretName != "" {
88+
addVolume := true
89+
for _, vol := range pod.Spec.Volumes {
90+
if vol.Name == secretVolumeName {
91+
addVolume = false
92+
}
93+
}
94+
if addVolume {
95+
pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{
96+
Name: secretVolumeName,
97+
VolumeSource: corev1.VolumeSource{
98+
Secret: &corev1.SecretVolumeSource{
99+
SecretName: exporter.TLS.SecretName,
100+
},
101+
}})
102+
}
103+
addVolumeMount := true
104+
for _, vol := range container.VolumeMounts {
105+
if vol.Name == secretVolumeName {
106+
addVolumeMount = false
107+
}
108+
}
109+
if addVolumeMount {
110+
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
111+
Name: secretVolumeName,
112+
MountPath: secretMountPath,
113+
ReadOnly: true,
114+
})
115+
}
116+
}
117+
118+
if exporter.TLS.ConfigMapName != "" {
119+
addVolume := true
120+
for _, vol := range pod.Spec.Volumes {
121+
if vol.Name == configMapVolumeName {
122+
addVolume = false
123+
}
124+
}
125+
if addVolume {
126+
pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{
127+
Name: configMapVolumeName,
128+
VolumeSource: corev1.VolumeSource{
129+
ConfigMap: &corev1.ConfigMapVolumeSource{
130+
LocalObjectReference: corev1.LocalObjectReference{
131+
Name: exporter.TLS.ConfigMapName,
132+
},
133+
},
134+
}})
135+
}
136+
addVolumeMount := true
137+
for _, vol := range container.VolumeMounts {
138+
if vol.Name == configMapVolumeName {
139+
addVolumeMount = false
140+
}
141+
}
142+
if addVolumeMount {
143+
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
144+
Name: configMapVolumeName,
145+
MountPath: configMapMountPath,
146+
ReadOnly: true,
147+
})
148+
}
149+
}
150+
}

pkg/instrumentation/exporter_test.go

+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package instrumentation
16+
17+
import (
18+
"testing"
19+
20+
"github.com/stretchr/testify/assert"
21+
corev1 "k8s.io/api/core/v1"
22+
23+
"github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1"
24+
)
25+
26+
func TestExporter(t *testing.T) {
27+
tests := []struct {
28+
name string
29+
exporter v1alpha1.Exporter
30+
expected corev1.Pod
31+
}{
32+
{
33+
name: "ca, crt and key from secret",
34+
exporter: v1alpha1.Exporter{
35+
Endpoint: "http://collector:4318",
36+
TLS: &v1alpha1.TLS{
37+
SecretName: "my-certs",
38+
CA: "ca.crt",
39+
Cert: "cert.crt",
40+
Key: "key.key",
41+
},
42+
},
43+
expected: corev1.Pod{
44+
Spec: corev1.PodSpec{
45+
Volumes: []corev1.Volume{
46+
{
47+
Name: "opentelemetry-auto-instrumentation-secret-my-certs",
48+
VolumeSource: corev1.VolumeSource{
49+
Secret: &corev1.SecretVolumeSource{
50+
SecretName: "my-certs",
51+
},
52+
},
53+
},
54+
},
55+
Containers: []corev1.Container{
56+
{
57+
VolumeMounts: []corev1.VolumeMount{
58+
{
59+
Name: "opentelemetry-auto-instrumentation-secret-my-certs",
60+
ReadOnly: true,
61+
MountPath: "/otel-auto-instrumentation-secret-my-certs",
62+
},
63+
},
64+
Env: []corev1.EnvVar{
65+
{
66+
Name: "OTEL_EXPORTER_OTLP_ENDPOINT",
67+
Value: "http://collector:4318",
68+
},
69+
{
70+
Name: "OTEL_EXPORTER_OTLP_CERTIFICATE",
71+
Value: "/otel-auto-instrumentation-secret-my-certs/ca.crt",
72+
},
73+
{
74+
Name: "OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE",
75+
Value: "/otel-auto-instrumentation-secret-my-certs/cert.crt",
76+
},
77+
{
78+
Name: "OTEL_EXPORTER_OTLP_CLIENT_KEY",
79+
Value: "/otel-auto-instrumentation-secret-my-certs/key.key",
80+
},
81+
},
82+
},
83+
},
84+
},
85+
},
86+
},
87+
{
88+
name: "crt and key from secret and ca from configmap",
89+
exporter: v1alpha1.Exporter{
90+
Endpoint: "http://collector:4318",
91+
TLS: &v1alpha1.TLS{
92+
SecretName: "my-certs",
93+
ConfigMapName: "ca-bundle",
94+
CA: "ca.crt",
95+
Cert: "cert.crt",
96+
Key: "key.key",
97+
},
98+
},
99+
expected: corev1.Pod{
100+
Spec: corev1.PodSpec{
101+
Volumes: []corev1.Volume{
102+
{
103+
Name: "opentelemetry-auto-instrumentation-secret-my-certs",
104+
VolumeSource: corev1.VolumeSource{
105+
Secret: &corev1.SecretVolumeSource{
106+
SecretName: "my-certs",
107+
},
108+
},
109+
},
110+
{
111+
Name: "opentelemetry-auto-instrumentation-configmap-ca-bundle",
112+
VolumeSource: corev1.VolumeSource{
113+
ConfigMap: &corev1.ConfigMapVolumeSource{
114+
LocalObjectReference: corev1.LocalObjectReference{
115+
Name: "ca-bundle",
116+
},
117+
},
118+
},
119+
},
120+
},
121+
Containers: []corev1.Container{
122+
{
123+
VolumeMounts: []corev1.VolumeMount{
124+
{
125+
Name: "opentelemetry-auto-instrumentation-secret-my-certs",
126+
ReadOnly: true,
127+
MountPath: "/otel-auto-instrumentation-secret-my-certs",
128+
},
129+
{
130+
Name: "opentelemetry-auto-instrumentation-configmap-ca-bundle",
131+
ReadOnly: true,
132+
MountPath: "/otel-auto-instrumentation-configmap-ca-bundle",
133+
},
134+
},
135+
Env: []corev1.EnvVar{
136+
{
137+
Name: "OTEL_EXPORTER_OTLP_ENDPOINT",
138+
Value: "http://collector:4318",
139+
},
140+
{
141+
Name: "OTEL_EXPORTER_OTLP_CERTIFICATE",
142+
Value: "/otel-auto-instrumentation-configmap-ca-bundle/ca.crt",
143+
},
144+
{
145+
Name: "OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE",
146+
Value: "/otel-auto-instrumentation-secret-my-certs/cert.crt",
147+
},
148+
{
149+
Name: "OTEL_EXPORTER_OTLP_CLIENT_KEY",
150+
Value: "/otel-auto-instrumentation-secret-my-certs/key.key",
151+
},
152+
},
153+
},
154+
},
155+
},
156+
},
157+
},
158+
{
159+
name: "ca, crt key absolute paths",
160+
exporter: v1alpha1.Exporter{
161+
Endpoint: "http://collector:4318",
162+
TLS: &v1alpha1.TLS{
163+
CA: "/ca.crt",
164+
Cert: "/cert.crt",
165+
Key: "/key.key",
166+
},
167+
},
168+
expected: corev1.Pod{
169+
Spec: corev1.PodSpec{
170+
Containers: []corev1.Container{
171+
{
172+
Env: []corev1.EnvVar{
173+
{
174+
Name: "OTEL_EXPORTER_OTLP_ENDPOINT",
175+
Value: "http://collector:4318",
176+
},
177+
{
178+
Name: "OTEL_EXPORTER_OTLP_CERTIFICATE",
179+
Value: "/ca.crt",
180+
},
181+
{
182+
Name: "OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE",
183+
Value: "/cert.crt",
184+
},
185+
{
186+
Name: "OTEL_EXPORTER_OTLP_CLIENT_KEY",
187+
Value: "/key.key",
188+
},
189+
},
190+
},
191+
},
192+
},
193+
},
194+
},
195+
}
196+
for _, test := range tests {
197+
t.Run(test.name, func(t *testing.T) {
198+
pod := corev1.Pod{
199+
Spec: corev1.PodSpec{
200+
Containers: []corev1.Container{
201+
{},
202+
},
203+
},
204+
}
205+
configureExporter(test.exporter, &pod, &pod.Spec.Containers[0])
206+
assert.Equal(t, test.expected, pod)
207+
})
208+
}
209+
}

0 commit comments

Comments
 (0)