Skip to content

Commit 8ebdc73

Browse files
committed
Imagepull secrets for extproc image
Signed-off-by: Johnu George <[email protected]>
1 parent fe9434a commit 8ebdc73

File tree

7 files changed

+79
-2
lines changed

7 files changed

+79
-2
lines changed

cmd/controller/main.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type flags struct {
4747
spanRequestHeaderAttributes string
4848
rootPrefix string
4949
extProcExtraEnvVars string
50+
extProcImagePullSecrets string
5051
// extProcMaxRecvMsgSize is the maximum message size in bytes that the gRPC server can receive.
5152
extProcMaxRecvMsgSize int
5253
// maxRecvMsgSize is the maximum message size in bytes that the gRPC extension server can receive.
@@ -143,6 +144,11 @@ func parseAndValidateFlags(args []string) (flags, error) {
143144
"",
144145
"Semicolon-separated key=value pairs for extra environment variables in extProc container. Format: OTEL_SERVICE_NAME=ai-gateway;OTEL_TRACES_EXPORTER=otlp",
145146
)
147+
extProcImagePullSecrets := fs.String(
148+
"extProcImagePullSecrets",
149+
"",
150+
"Semicolon-separated list of image pull secret names for extProc container. Format: my-registry-secret;another-secret",
151+
)
146152
extProcMaxRecvMsgSize := fs.Int(
147153
"extProcMaxRecvMsgSize",
148154
512*1024*1024,
@@ -205,6 +211,14 @@ func parseAndValidateFlags(args []string) (flags, error) {
205211
}
206212
}
207213

214+
// Validate extProc image pull secrets if provided.
215+
if *extProcImagePullSecrets != "" {
216+
_, err := controller.ParseImagePullSecrets(*extProcImagePullSecrets)
217+
if err != nil {
218+
return flags{}, fmt.Errorf("invalid extProc image pull secrets: %w", err)
219+
}
220+
}
221+
208222
return flags{
209223
extProcLogLevel: *extProcLogLevelPtr,
210224
extProcImage: *extProcImagePtr,
@@ -221,6 +235,7 @@ func parseAndValidateFlags(args []string) (flags, error) {
221235
spanRequestHeaderAttributes: *spanRequestHeaderAttributes,
222236
rootPrefix: *rootPrefix,
223237
extProcExtraEnvVars: *extProcExtraEnvVars,
238+
extProcImagePullSecrets: *extProcImagePullSecrets,
224239
extProcMaxRecvMsgSize: *extProcMaxRecvMsgSize,
225240
maxRecvMsgSize: *maxRecvMsgSize,
226241
}, nil
@@ -304,6 +319,7 @@ func main() {
304319
TracingRequestHeaderAttributes: flags.spanRequestHeaderAttributes,
305320
RootPrefix: flags.rootPrefix,
306321
ExtProcExtraEnvVars: flags.extProcExtraEnvVars,
322+
ExtProcImagePullSecrets: flags.extProcImagePullSecrets,
307323
ExtProcMaxRecvMsgSize: flags.extProcMaxRecvMsgSize,
308324
}); err != nil {
309325
setupLog.Error(err, "failed to start controller")

internal/controller/controller.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ type Options struct {
8181
RootPrefix string
8282
// ExtProcExtraEnvVars is the semicolon-separated key=value pairs for extra environment variables in extProc container.
8383
ExtProcExtraEnvVars string
84+
// ExtProcImagePullSecrets is the semicolon-separated list of image pull secret names for extProc container.
85+
ExtProcImagePullSecrets string
8486
// ExtProcMaxRecvMsgSize is the maximum message size in bytes that the gRPC server can receive for extProc.
8587
ExtProcMaxRecvMsgSize int
8688
}
@@ -211,6 +213,7 @@ func StartControllers(ctx context.Context, mgr manager.Manager, config *rest.Con
211213
options.TracingRequestHeaderAttributes,
212214
options.RootPrefix,
213215
options.ExtProcExtraEnvVars,
216+
options.ExtProcImagePullSecrets,
214217
options.ExtProcMaxRecvMsgSize,
215218
isKubernetes133OrLater(versionInfo, logger),
216219
))

internal/controller/gateway_mutator.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type gatewayMutator struct {
4242
spanRequestHeaderAttributes string
4343
rootPrefix string
4444
extProcExtraEnvVars []corev1.EnvVar
45+
extProcImagePullSecrets []corev1.LocalObjectReference
4546
extProcMaxRecvMsgSize int
4647

4748
// Whether to run the extProc container as a sidecar (true) as a normal container (false).
@@ -51,7 +52,7 @@ type gatewayMutator struct {
5152

5253
func newGatewayMutator(c client.Client, kube kubernetes.Interface, logger logr.Logger,
5354
extProcImage string, extProcImagePullPolicy corev1.PullPolicy, extProcLogLevel,
54-
udsPath, metricsRequestHeaderAttributes, spanRequestHeaderAttributes, rootPrefix, extProcExtraEnvVars string, extProcMaxRecvMsgSize int,
55+
udsPath, metricsRequestHeaderAttributes, spanRequestHeaderAttributes, rootPrefix, extProcExtraEnvVars, extProcImagePullSecrets string, extProcMaxRecvMsgSize int,
5556
extProcAsSideCar bool,
5657
) *gatewayMutator {
5758
var parsedEnvVars []corev1.EnvVar
@@ -63,6 +64,17 @@ func newGatewayMutator(c client.Client, kube kubernetes.Interface, logger logr.L
6364
"envVars", extProcExtraEnvVars)
6465
}
6566
}
67+
68+
var parsedImagePullSecrets []corev1.LocalObjectReference
69+
if extProcImagePullSecrets != "" {
70+
var err error
71+
parsedImagePullSecrets, err = ParseImagePullSecrets(extProcImagePullSecrets)
72+
if err != nil {
73+
logger.Error(err, "failed to parse extProc image pull secrets, skipping",
74+
"imagePullSecrets", extProcImagePullSecrets)
75+
}
76+
}
77+
6678
return &gatewayMutator{
6779
c: c, codec: serializer.NewCodecFactory(Scheme),
6880
kube: kube,
@@ -75,6 +87,7 @@ func newGatewayMutator(c client.Client, kube kubernetes.Interface, logger logr.L
7587
spanRequestHeaderAttributes: spanRequestHeaderAttributes,
7688
rootPrefix: rootPrefix,
7789
extProcExtraEnvVars: parsedEnvVars,
90+
extProcImagePullSecrets: parsedImagePullSecrets,
7891
extProcMaxRecvMsgSize: extProcMaxRecvMsgSize,
7992
extProcAsSideCar: extProcAsSideCar,
8093
}
@@ -167,6 +180,31 @@ func ParseExtraEnvVars(s string) ([]corev1.EnvVar, error) {
167180
return result, nil
168181
}
169182

183+
// ParseImagePullSecrets parses semicolon-separated secret names into a list of
184+
// LocalObjectReference objects for image pull secrets.
185+
// Example: "my-registry-secret;another-secret".
186+
func ParseImagePullSecrets(s string) ([]corev1.LocalObjectReference, error) {
187+
if s == "" {
188+
return nil, nil
189+
}
190+
191+
names := strings.Split(s, ";")
192+
result := make([]corev1.LocalObjectReference, 0, len(names))
193+
for _, name := range names {
194+
name = strings.TrimSpace(name)
195+
if name == "" {
196+
continue // Skip empty names from trailing semicolons.
197+
}
198+
result = append(result, corev1.LocalObjectReference{Name: name})
199+
}
200+
201+
if len(result) == 0 {
202+
return nil, nil
203+
}
204+
205+
return result, nil
206+
}
207+
170208
func (g *gatewayMutator) mutatePod(ctx context.Context, pod *corev1.Pod, gatewayName, gatewayNamespace string) error {
171209
var routes aigv1a1.AIGatewayRouteList
172210
err := g.c.List(ctx, &routes, client.MatchingFields{
@@ -223,6 +261,11 @@ func (g *gatewayMutator) mutatePod(ctx context.Context, pod *corev1.Pod, gateway
223261
},
224262
)
225263

264+
// Add imagePullSecrets for extProc if configured
265+
if len(g.extProcImagePullSecrets) > 0 {
266+
podspec.ImagePullSecrets = append(podspec.ImagePullSecrets, g.extProcImagePullSecrets...)
267+
}
268+
226269
// Currently, we have to set the resources for the extproc container at route level.
227270
// We choose one of the routes to set the resources for the extproc container.
228271
var resources corev1.ResourceRequirements

internal/controller/gateway_mutator_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func newTestGatewayMutator(fakeClient client.Client, fakeKube *fake2.Clientset,
187187
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true, Level: zapcore.DebugLevel})))
188188
return newGatewayMutator(
189189
fakeClient, fakeKube, ctrl.Log, "docker.io/envoyproxy/ai-gateway-extproc:latest", corev1.PullIfNotPresent,
190-
"info", "/tmp/extproc.sock", metricsRequestHeaderAttributes, spanRequestHeaderAttributes, "/v1", extProcExtraEnvVars, 512*1024*1024,
190+
"info", "/tmp/extproc.sock", metricsRequestHeaderAttributes, spanRequestHeaderAttributes, "/v1", extProcExtraEnvVars, "", 512*1024*1024,
191191
sidecar,
192192
)
193193
}

manifests/charts/ai-gateway-helm/templates/_helpers.tpl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,14 @@ Convert extraEnvVars array to semicolon-separated string for extProc
7878
{{- end -}}
7979
{{- join ";" $envVars -}}
8080
{{- end }}
81+
82+
{{/*
83+
Convert imagePullSecrets array to semicolon-separated string for extProc
84+
*/}}
85+
{{- define "ai-gateway-helm.extProc.imagePullSecretsString" -}}
86+
{{- $secrets := list -}}
87+
{{- range .Values.extProc.imagePullSecrets -}}
88+
{{- $secrets = append $secrets .name -}}
89+
{{- end -}}
90+
{{- join ";" $secrets -}}
91+
{{- end }}

manifests/charts/ai-gateway-helm/templates/deployment.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ spec:
4646
- --extProcImage={{ .Values.extProc.image.repository }}:{{ .Values.extProc.image.tag | default .Chart.AppVersion }}
4747
- --extProcImagePullPolicy={{ .Values.extProc.imagePullPolicy }}
4848
- --extProcLogLevel={{ .Values.extProc.logLevel }}
49+
{{- if .Values.extProc.imagePullSecrets }}
50+
- --extProcImagePullSecrets={{ include "ai-gateway-helm.extProc.imagePullSecretsString" . }}
51+
{{- end }}
4952
{{- if or .Values.controller.metricsRequestHeaderAttributes .Values.controller.metricsRequestHeaderLabels }}
5053
- --metricsRequestHeaderAttributes={{ .Values.controller.metricsRequestHeaderAttributes | default .Values.controller.metricsRequestHeaderLabels }}
5154
{{- end }}

manifests/charts/ai-gateway-helm/values.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extProc:
2121
# Overrides the image tag whose default is the chart appVersion.
2222
tag: ""
2323
imagePullPolicy: IfNotPresent
24+
imagePullSecrets: []
2425
# One of "info", "debug", "trace", "warn", "error", "fatal", "panic".
2526
logLevel: info
2627

0 commit comments

Comments
 (0)