Skip to content

Commit 4555ca6

Browse files
committed
Adding key field to proxyCA config.
1 parent 177fc01 commit 4555ca6

File tree

17 files changed

+306
-117
lines changed

17 files changed

+306
-117
lines changed

api/v1alpha1/olsconfig_types.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,9 +524,24 @@ type ProxyConfig struct {
524524
// +kubebuilder:validation:Pattern=`^https?://.*$`
525525
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Proxy URL"
526526
ProxyURL string `json:"proxyURL,omitempty"`
527-
// The configmap holding proxy CA certificate
527+
// The configmap and key holding proxy CA certificate.
528+
// The key is optional and defaults to "proxy-ca.crt" for backward compatibility.
529+
// If you use a different key name in your ConfigMap, specify it in the Key field of ProxyCACertConfigMapRef.
528530
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Proxy CA Certificate"
529-
ProxyCACertificateRef *corev1.LocalObjectReference `json:"proxyCACertificate,omitempty"`
531+
ProxyCACertificateRef *ProxyCACertConfigMapRef `json:"proxyCACertificate,omitempty"`
532+
}
533+
534+
// ProxyCACertConfigMapRef references a ConfigMap containing the proxy CA certificate.
535+
// Provides backward compatibility by making the key field optional with a default value.
536+
// +structType=atomic
537+
type ProxyCACertConfigMapRef struct {
538+
// The ConfigMap to select from
539+
corev1.LocalObjectReference `json:",inline"`
540+
// Key in the ConfigMap that contains the proxy CA certificate.
541+
// Defaults to "proxy-ca.crt" if not specified.
542+
// +kubebuilder:default="proxy-ca.crt"
543+
// +optional
544+
Key string `json:"key,omitempty"`
530545
}
531546

532547
// ToolFilteringConfig defines configuration for tool filtering using hybrid RAG retrieval.

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 17 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/ols.openshift.io_olsconfigs.yaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4346,8 +4346,17 @@ spec:
43464346
such as LLM providers.
43474347
properties:
43484348
proxyCACertificate:
4349-
description: The configmap holding proxy CA certificate
4349+
description: |-
4350+
The configmap and key holding proxy CA certificate.
4351+
The key is optional and defaults to "proxy-ca.crt" for backward compatibility.
4352+
If you use a different key name in your ConfigMap, specify it in the Key field of ProxyCACertConfigMapRef.
43504353
properties:
4354+
key:
4355+
default: proxy-ca.crt
4356+
description: |-
4357+
Key in the ConfigMap that contains the proxy CA certificate.
4358+
Defaults to "proxy-ca.crt" if not specified.
4359+
type: string
43514360
name:
43524361
default: ""
43534362
description: |-

internal/controller/appserver/assets.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,15 @@ func GenerateOLSConfigMap(r reconciler.Reconciler, ctx context.Context, cr *olsv
191191
ProxyURL: cr.Spec.OLSConfig.ProxyConfig.ProxyURL,
192192
ProxyCACertPath: "",
193193
}
194-
if cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef != nil && cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name != "" {
195-
err := validateCertificateInConfigMap(r, ctx, cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name, utils.ProxyCACertFileName)
194+
proxyCACertRef := cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef
195+
cmName := utils.GetProxyCACertConfigMapName(proxyCACertRef)
196+
if cmName != "" {
197+
certKey := utils.GetProxyCACertKey(proxyCACertRef)
198+
err := validateCertificateInConfigMap(r, ctx, cmName, certKey)
196199
if err != nil {
197-
return nil, fmt.Errorf("failed to validate proxy CA certificate %s: %w", cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name, err)
200+
return nil, fmt.Errorf("failed to validate proxy CA certificate %s: %w", cmName, err)
198201
}
199-
proxyConfig.ProxyCACertPath = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName, utils.ProxyCACertFileName)
202+
proxyConfig.ProxyCACertPath = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName, certKey)
200203
}
201204
}
202205

internal/controller/appserver/assets_test.go

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,7 @@ user_data_collector_config: {}
16401640

16411641
Context("Proxy settings", func() {
16421642
const caConfigMapName = "test-ca-configmap"
1643+
const proxyURL = "https://proxy.example.com:8080"
16431644
var proxyCACm *corev1.ConfigMap
16441645

16451646
BeforeEach(func() {
@@ -1713,15 +1714,19 @@ user_data_collector_config: {}
17131714
))
17141715

17151716
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
1716-
ProxyURL: "https://proxy.example.com:8080",
1717-
ProxyCACertificateRef: &corev1.LocalObjectReference{
1718-
Name: caConfigMapName,
1717+
ProxyURL: proxyURL,
1718+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
1719+
LocalObjectReference: corev1.LocalObjectReference{
1720+
Name: caConfigMapName,
1721+
},
1722+
// No Key specified - tests backward compatibility
17191723
},
17201724
}
17211725

17221726
olsCm, err = GenerateOLSConfigMap(testReconcilerInstance, ctx, cr)
17231727
Expect(err).NotTo(HaveOccurred())
1724-
Expect(olsCm.Data[utils.OLSConfigFilename]).To(ContainSubstring("proxy_config:\n proxy_ca_cert_path: /etc/certs/proxy-ca/proxy-ca.crt\n proxy_url: https://proxy.example.com:8080\n"))
1728+
Expect(olsCm.Data[utils.OLSConfigFilename]).To(ContainSubstring("proxy_ca_cert_path: /etc/certs/proxy-ca/" + utils.ProxyCACertFileName))
1729+
Expect(olsCm.Data[utils.OLSConfigFilename]).To(ContainSubstring("proxy_url: " + proxyURL))
17251730

17261731
dep, err = GenerateOLSDeployment(testReconcilerInstance, cr)
17271732
Expect(err).NotTo(HaveOccurred())
@@ -1734,6 +1739,9 @@ user_data_collector_config: {}
17341739
Name: caConfigMapName,
17351740
},
17361741
DefaultMode: &defaultVolumeMode,
1742+
Items: []corev1.KeyToPath{
1743+
{Key: utils.ProxyCACertFileName, Path: utils.ProxyCACertFileName},
1744+
},
17371745
},
17381746
},
17391747
}))
@@ -1752,15 +1760,38 @@ user_data_collector_config: {}
17521760
Expect(err).NotTo(HaveOccurred())
17531761

17541762
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
1755-
ProxyURL: "https://proxy.example.com:8080",
1756-
ProxyCACertificateRef: &corev1.LocalObjectReference{
1757-
Name: caConfigMapName,
1763+
ProxyURL: proxyURL,
1764+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
1765+
LocalObjectReference: corev1.LocalObjectReference{
1766+
Name: caConfigMapName,
1767+
},
1768+
// No Key specified - tests backward compatibility
17581769
},
17591770
}
17601771
_, err = GenerateOLSConfigMap(testReconcilerInstance, ctx, cr)
17611772
Expect(err).To(HaveOccurred())
17621773
Expect(err.Error()).To(ContainSubstring("failed to validate proxy CA certificate"))
17631774
})
1775+
1776+
It("should use custom Key when ProxyCACertificateRef.Key is set", func() {
1777+
const proxyCertKey = "my-proxy-ca.crt"
1778+
proxyCACm.Data[proxyCertKey] = utils.TestCACert
1779+
err := testReconcilerInstance.Update(ctx, proxyCACm)
1780+
Expect(err).NotTo(HaveOccurred())
1781+
1782+
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
1783+
ProxyURL: proxyURL,
1784+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
1785+
LocalObjectReference: corev1.LocalObjectReference{Name: caConfigMapName},
1786+
Key: proxyCertKey,
1787+
},
1788+
}
1789+
1790+
olsCm, err := GenerateOLSConfigMap(testReconcilerInstance, ctx, cr)
1791+
Expect(err).NotTo(HaveOccurred())
1792+
Expect(olsCm.Data[utils.OLSConfigFilename]).To(ContainSubstring("proxy_ca_cert_path: /etc/certs/proxy-ca/" + proxyCertKey))
1793+
Expect(olsCm.Data[utils.OLSConfigFilename]).To(ContainSubstring("proxy_url: " + proxyURL))
1794+
})
17641795
})
17651796
})
17661797

internal/controller/appserver/deployment.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,18 @@ func GenerateOLSDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) (
263263
// User provided CA certificates - create both volumes and volume mounts in single pass
264264
_ = utils.ForEachExternalConfigMap(cr, func(name, source string) error {
265265
var volumeName, mountPath string
266+
var items []corev1.KeyToPath
266267
switch source {
267268
case "additional-ca":
268269
volumeName = utils.AdditionalCAVolumeName
269270
mountPath = UserCAMountPath
270271
case "proxy-ca":
271272
volumeName = utils.ProxyCACertVolumeName
272273
mountPath = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName)
274+
certKey := utils.GetProxyCACertKey(cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef)
275+
items = []corev1.KeyToPath{
276+
{Key: certKey, Path: certKey},
277+
}
273278
default:
274279
return nil
275280
}
@@ -280,6 +285,7 @@ func GenerateOLSDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) (
280285
ConfigMap: &corev1.ConfigMapVolumeSource{
281286
LocalObjectReference: corev1.LocalObjectReference{Name: name},
282287
DefaultMode: &volumeDefaultMode,
288+
Items: items,
283289
},
284290
},
285291
})
@@ -358,13 +364,16 @@ func GenerateOLSDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) (
358364
// If they don't exist, we'll get empty strings which is fine for initial creation
359365
configMapResourceVersion, _ := utils.GetConfigMapResourceVersion(r, ctx, utils.OLSConfigCmName)
360366

367+
proxyCACMResourceVersion := utils.GetProxyCACertResourceVersion(r, ctx, cr)
368+
361369
deployment := appsv1.Deployment{
362370
ObjectMeta: metav1.ObjectMeta{
363371
Name: utils.OLSAppServerDeploymentName,
364372
Namespace: r.GetNamespace(),
365373
Labels: utils.GenerateAppServerSelectorLabels(),
366374
Annotations: map[string]string{
367-
utils.OLSConfigMapResourceVersionAnnotation: configMapResourceVersion,
375+
utils.OLSConfigMapResourceVersionAnnotation: configMapResourceVersion,
376+
utils.ProxyCACertResourceVersionAnnotation: proxyCACMResourceVersion,
368377
},
369378
},
370379
Spec: appsv1.DeploymentSpec{
@@ -521,14 +530,28 @@ func updateOLSDeployment(r reconciler.Reconciler, ctx context.Context, existingD
521530
}
522531
}
523532

533+
// Step 3: Check if Proxy CA ConfigMap ResourceVersion has changed
534+
storedProxyCACMVersion := existingDeployment.Annotations[utils.ProxyCACertResourceVersionAnnotation]
535+
currentProxyCACMVersion := desiredDeployment.Annotations[utils.ProxyCACertResourceVersionAnnotation]
536+
if storedProxyCACMVersion != currentProxyCACMVersion {
537+
changed = true
538+
}
539+
524540
// If nothing changed, skip update
525541
if !changed {
526542
return nil
527543
}
528544

529545
// Apply changes - always update spec and annotations since something changed
530546
existingDeployment.Spec = desiredDeployment.Spec
547+
548+
// Initialize annotations if nil
549+
if existingDeployment.Annotations == nil {
550+
existingDeployment.Annotations = make(map[string]string)
551+
}
552+
531553
existingDeployment.Annotations[utils.OLSConfigMapResourceVersionAnnotation] = desiredDeployment.Annotations[utils.OLSConfigMapResourceVersionAnnotation]
554+
existingDeployment.Annotations[utils.ProxyCACertResourceVersionAnnotation] = desiredDeployment.Annotations[utils.ProxyCACertResourceVersionAnnotation]
532555

533556
r.GetLogger().Info("updating OLS deployment", "name", existingDeployment.Name)
534557

internal/controller/appserver/reconciler.go

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func ReconcileAppServerResources(r reconciler.Reconciler, ctx context.Context, o
6464
},
6565
{
6666
Name: "reconcile Additional CA ConfigMap",
67-
Task: reconcileOLSAdditionalCAConfigMap,
67+
Task: utils.ReconcileOLSAdditionalCAConfigMap,
6868
},
6969
{
7070
Name: "reconcile Metrics Reader Secret",
@@ -76,7 +76,7 @@ func ReconcileAppServerResources(r reconciler.Reconciler, ctx context.Context, o
7676
},
7777
{
7878
Name: "reconcile Proxy CA ConfigMap",
79-
Task: reconcileProxyCAConfigMap,
79+
Task: utils.ReconcileProxyCAConfigMap,
8080
},
8181
{
8282
Name: "reconcile ImageStreams",
@@ -185,24 +185,6 @@ func reconcileOLSConfigMap(r reconciler.Reconciler, ctx context.Context, cr *ols
185185
return nil
186186
}
187187

188-
func reconcileOLSAdditionalCAConfigMap(r reconciler.Reconciler, ctx context.Context, cr *olsv1alpha1.OLSConfig) error {
189-
if cr.Spec.OLSConfig.AdditionalCAConfigMapRef == nil {
190-
// no additional CA certs, skip
191-
r.GetLogger().Info("Additional CA not configured, reconciliation skipped")
192-
return nil
193-
}
194-
195-
// Verify the configmap exists (annotation is handled by main controller)
196-
cm := &corev1.ConfigMap{}
197-
err := r.Get(ctx, client.ObjectKey{Name: cr.Spec.OLSConfig.AdditionalCAConfigMapRef.Name, Namespace: r.GetNamespace()}, cm)
198-
if err != nil {
199-
return fmt.Errorf("%s: %w", utils.ErrGetAdditionalCACM, err)
200-
}
201-
202-
r.GetLogger().Info("additional CA configmap reconciled", "configmap", cm.Name)
203-
return nil
204-
}
205-
206188
func reconcileExporterConfigMap(r reconciler.Reconciler, ctx context.Context, cr *olsv1alpha1.OLSConfig) error {
207189
// Check if data collector is enabled
208190
enabled, err := dataCollectorEnabled(r, cr)
@@ -247,27 +229,6 @@ func reconcileExporterConfigMap(r reconciler.Reconciler, ctx context.Context, cr
247229
return nil
248230
}
249231

250-
func reconcileProxyCAConfigMap(r reconciler.Reconciler, ctx context.Context, cr *olsv1alpha1.OLSConfig) error {
251-
if cr.Spec.OLSConfig.ProxyConfig == nil || cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef == nil {
252-
// no proxy CA certs, skip
253-
r.GetLogger().Info("Proxy CA not configured, reconciliation skipped")
254-
return nil
255-
}
256-
257-
cm := &corev1.ConfigMap{}
258-
err := r.Get(ctx, client.ObjectKey{Name: cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name, Namespace: r.GetNamespace()}, cm)
259-
if err != nil {
260-
return fmt.Errorf("%s: %w", utils.ErrGetProxyCACM, err)
261-
}
262-
err = r.Update(ctx, cm)
263-
if err != nil {
264-
return fmt.Errorf("%s: %w", utils.ErrUpdateProxyCACM, err)
265-
}
266-
267-
r.GetLogger().Info("proxy CA configmap reconciled", "configmap", cm.Name)
268-
return nil
269-
}
270-
271232
func reconcileServiceAccount(r reconciler.Reconciler, ctx context.Context, cr *olsv1alpha1.OLSConfig) error {
272233
sa, err := GenerateServiceAccount(r, cr)
273234
if err != nil {

internal/controller/appserver/reconciler_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -981,8 +981,10 @@ var _ = Describe("App server reconciliator", Ordered, func() {
981981
By("Set up a proxy CA cert")
982982
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
983983
ProxyURL: "https://proxy.example.com:8080",
984-
ProxyCACertificateRef: &corev1.LocalObjectReference{
985-
Name: cmCACertName,
984+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
985+
LocalObjectReference: corev1.LocalObjectReference{
986+
Name: cmCACertName,
987+
},
986988
},
987989
}
988990
err := ReconcileAppServer(testReconcilerInstance, ctx, cr)
@@ -1008,6 +1010,9 @@ var _ = Describe("App server reconciliator", Ordered, func() {
10081010
Name: cmCACertName,
10091011
},
10101012
DefaultMode: &volumeDefaultMode,
1013+
Items: []corev1.KeyToPath{
1014+
{Key: utils.ProxyCACertFileName, Path: utils.ProxyCACertFileName},
1015+
},
10111016
},
10121017
},
10131018
},

internal/controller/lcore/config.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ func buildLCoreServiceConfig(_ reconciler.Reconciler, cr *olsv1alpha1.OLSConfig)
637637
// color_log: enable colored logs for DEBUG, disable for production (INFO+)
638638
colorLog := logLevel == olsv1alpha1.LogLevelDebug
639639

640-
return map[string]interface{}{
640+
serviceConfig := map[string]interface{}{
641641
"host": "0.0.0.0",
642642
"port": utils.OLSAppServerContainerPort,
643643
"auth_enabled": false,
@@ -651,6 +651,28 @@ func buildLCoreServiceConfig(_ reconciler.Reconciler, cr *olsv1alpha1.OLSConfig)
651651
"tls_key_path": "/etc/certs/lightspeed-tls/tls.key",
652652
},
653653
}
654+
655+
// Add proxy configuration if specified
656+
if cr.Spec.OLSConfig.ProxyConfig != nil {
657+
proxyConfigMap := map[string]interface{}{}
658+
659+
if cr.Spec.OLSConfig.ProxyConfig.ProxyURL != "" {
660+
proxyConfigMap["proxy_url"] = cr.Spec.OLSConfig.ProxyConfig.ProxyURL
661+
}
662+
663+
proxyCACertRef := cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef
664+
cmName := utils.GetProxyCACertConfigMapName(proxyCACertRef)
665+
if cmName != "" {
666+
certKey := utils.GetProxyCACertKey(proxyCACertRef)
667+
proxyConfigMap["proxy_ca_cert_path"] = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName, certKey)
668+
}
669+
670+
if len(proxyConfigMap) > 0 {
671+
serviceConfig["proxy_config"] = proxyConfigMap
672+
}
673+
}
674+
675+
return serviceConfig
654676
}
655677

656678
func buildLCoreLlamaStackConfig(r reconciler.Reconciler, _ *olsv1alpha1.OLSConfig) map[string]interface{} {

0 commit comments

Comments
 (0)