Skip to content

Commit f8574c5

Browse files
committed
Adding key field to proxyCA config.
1 parent 5738e2c commit f8574c5

File tree

16 files changed

+273
-39
lines changed

16 files changed

+273
-39
lines changed

api/v1alpha1/olsconfig_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,9 @@ type ProxyConfig struct {
511511
// +kubebuilder:validation:Pattern=`^https?://.*$`
512512
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Proxy URL"
513513
ProxyURL string `json:"proxyURL,omitempty"`
514-
// The configmap holding proxy CA certificate
514+
// The configmap and key holding proxy CA certificate
515515
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Proxy CA Certificate"
516-
ProxyCACertificateRef *corev1.LocalObjectReference `json:"proxyCACertificate,omitempty"`
516+
ProxyCACertificateRef *corev1.ConfigMapKeySelector `json:"proxyCACertificate,omitempty"`
517517
}
518518

519519
// MCPServer defines the settings for a single MCP server.

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 2 additions & 2 deletions
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
@@ -935,8 +935,11 @@ spec:
935935
such as LLM providers.
936936
properties:
937937
proxyCACertificate:
938-
description: The configmap holding proxy CA certificate
938+
description: The configmap and key holding proxy CA certificate
939939
properties:
940+
key:
941+
description: The key to select.
942+
type: string
940943
name:
941944
default: ""
942945
description: |-
@@ -946,6 +949,12 @@ spec:
946949
almost certainly wrong.
947950
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
948951
type: string
952+
optional:
953+
description: Specify whether the ConfigMap or its key
954+
must be defined
955+
type: boolean
956+
required:
957+
- key
949958
type: object
950959
x-kubernetes-map-type: atomic
951960
proxyURL:

internal/controller/appserver/assets.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,15 @@ func GenerateOLSConfigMap(r reconciler.Reconciler, ctx context.Context, cr *olsv
184184
ProxyURL: cr.Spec.OLSConfig.ProxyConfig.ProxyURL,
185185
ProxyCACertPath: "",
186186
}
187-
if cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef != nil && cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name != "" {
188-
err := validateCertificateInConfigMap(r, ctx, cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name, utils.ProxyCACertFileName)
187+
proxyCACertRef := cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef
188+
cmName := utils.GetProxyCACertConfigMapName(proxyCACertRef)
189+
if cmName != "" {
190+
certKey := utils.GetProxyCACertKey(proxyCACertRef)
191+
err := validateCertificateInConfigMap(r, ctx, cmName, certKey)
189192
if err != nil {
190-
return nil, fmt.Errorf("failed to validate proxy CA certificate %s: %w", cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name, err)
193+
return nil, fmt.Errorf("failed to validate proxy CA certificate %s: %w", cmName, err)
191194
}
192-
proxyConfig.ProxyCACertPath = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName, utils.ProxyCACertFileName)
195+
proxyConfig.ProxyCACertPath = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName, certKey)
193196
}
194197
}
195198

internal/controller/appserver/assets_test.go

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,8 +1623,11 @@ user_data_collector_config: {}
16231623

16241624
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
16251625
ProxyURL: "https://proxy.example.com:8080",
1626-
ProxyCACertificateRef: &corev1.LocalObjectReference{
1627-
Name: caConfigMapName,
1626+
ProxyCACertificateRef: &corev1.ConfigMapKeySelector{
1627+
LocalObjectReference: corev1.LocalObjectReference{
1628+
Name: caConfigMapName,
1629+
},
1630+
// No Key specified - tests backward compatibility
16281631
},
16291632
}
16301633

@@ -1643,6 +1646,12 @@ user_data_collector_config: {}
16431646
Name: caConfigMapName,
16441647
},
16451648
DefaultMode: &defaultVolumeMode,
1649+
Items: []corev1.KeyToPath{
1650+
{
1651+
Key: utils.ProxyCACertFileName,
1652+
Path: utils.ProxyCACertFileName,
1653+
},
1654+
},
16461655
},
16471656
},
16481657
}))
@@ -1662,14 +1671,58 @@ user_data_collector_config: {}
16621671

16631672
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
16641673
ProxyURL: "https://proxy.example.com:8080",
1665-
ProxyCACertificateRef: &corev1.LocalObjectReference{
1666-
Name: caConfigMapName,
1674+
ProxyCACertificateRef: &corev1.ConfigMapKeySelector{
1675+
LocalObjectReference: corev1.LocalObjectReference{
1676+
Name: caConfigMapName,
1677+
},
1678+
// No Key specified - tests backward compatibility
16671679
},
16681680
}
16691681
_, err = GenerateOLSConfigMap(testReconcilerInstance, ctx, cr)
16701682
Expect(err).To(HaveOccurred())
16711683
Expect(err.Error()).To(ContainSubstring("failed to validate proxy CA certificate"))
16721684
})
1685+
1686+
It("should support custom ConfigMap key for proxy CA certificate", func() {
1687+
customKey := "service-ca.crt"
1688+
proxyCACm.Data = map[string]string{
1689+
customKey: utils.TestCACert,
1690+
}
1691+
err := testReconcilerInstance.Update(ctx, proxyCACm)
1692+
Expect(err).NotTo(HaveOccurred())
1693+
1694+
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
1695+
ProxyURL: "https://proxy.example.com:8080",
1696+
ProxyCACertificateRef: &corev1.ConfigMapKeySelector{
1697+
LocalObjectReference: corev1.LocalObjectReference{
1698+
Name: caConfigMapName,
1699+
},
1700+
Key: customKey,
1701+
},
1702+
}
1703+
1704+
// Test OLS ConfigMap has correct path with custom key
1705+
olsCm, err := GenerateOLSConfigMap(testReconcilerInstance, ctx, cr)
1706+
Expect(err).NotTo(HaveOccurred())
1707+
Expect(olsCm.Data[utils.OLSConfigFilename]).To(ContainSubstring(
1708+
fmt.Sprintf("proxy_ca_cert_path: /etc/certs/proxy-ca/%s", customKey)))
1709+
1710+
// Test deployment has Items projection with custom key
1711+
dep, err := GenerateOLSDeployment(testReconcilerInstance, cr)
1712+
Expect(err).NotTo(HaveOccurred())
1713+
1714+
var proxyCAVolume *corev1.Volume
1715+
for i := range dep.Spec.Template.Spec.Volumes {
1716+
if dep.Spec.Template.Spec.Volumes[i].Name == utils.ProxyCACertVolumeName {
1717+
proxyCAVolume = &dep.Spec.Template.Spec.Volumes[i]
1718+
break
1719+
}
1720+
}
1721+
Expect(proxyCAVolume).NotTo(BeNil())
1722+
Expect(proxyCAVolume.ConfigMap.Items).To(HaveLen(1))
1723+
Expect(proxyCAVolume.ConfigMap.Items[0].Key).To(Equal(customKey))
1724+
Expect(proxyCAVolume.ConfigMap.Items[0].Path).To(Equal(customKey))
1725+
})
16731726
})
16741727
})
16751728

internal/controller/appserver/deployment.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -260,25 +260,43 @@ func GenerateOLSDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) (
260260
// User provided CA certificates - create both volumes and volume mounts in single pass
261261
_ = utils.ForEachExternalConfigMap(cr, func(name, source string) error {
262262
var volumeName, mountPath string
263+
var volumeSource corev1.VolumeSource
264+
263265
switch source {
264266
case "additional-ca":
265267
volumeName = utils.AdditionalCAVolumeName
266268
mountPath = UserCAMountPath
269+
volumeSource = corev1.VolumeSource{
270+
ConfigMap: &corev1.ConfigMapVolumeSource{
271+
LocalObjectReference: corev1.LocalObjectReference{Name: name},
272+
DefaultMode: &volumeDefaultMode,
273+
},
274+
}
267275
case "proxy-ca":
268276
volumeName = utils.ProxyCACertVolumeName
269277
mountPath = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName)
278+
// Get the key to use for the certificate
279+
proxyCACertRef := cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef
280+
certKey := utils.GetProxyCACertKey(proxyCACertRef)
281+
volumeSource = corev1.VolumeSource{
282+
ConfigMap: &corev1.ConfigMapVolumeSource{
283+
LocalObjectReference: corev1.LocalObjectReference{Name: name},
284+
DefaultMode: &volumeDefaultMode,
285+
Items: []corev1.KeyToPath{
286+
{
287+
Key: certKey,
288+
Path: certKey, // Mount with same filename as key
289+
},
290+
},
291+
},
292+
}
270293
default:
271294
return nil
272295
}
273296

274297
volumes = append(volumes, corev1.Volume{
275-
Name: volumeName,
276-
VolumeSource: corev1.VolumeSource{
277-
ConfigMap: &corev1.ConfigMapVolumeSource{
278-
LocalObjectReference: corev1.LocalObjectReference{Name: name},
279-
DefaultMode: &volumeDefaultMode,
280-
},
281-
},
298+
Name: volumeName,
299+
VolumeSource: volumeSource,
282300
})
283301

284302
volumeMounts = append(volumeMounts, corev1.VolumeMount{

internal/controller/appserver/reconciler.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,15 @@ func reconcileProxyCAConfigMap(r reconciler.Reconciler, ctx context.Context, cr
245245
return nil
246246
}
247247

248+
cmName := utils.GetProxyCACertConfigMapName(cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef)
249+
if cmName == "" {
250+
// no proxy CA certs, skip
251+
r.GetLogger().Info("Proxy CA not configured, reconciliation skipped")
252+
return nil
253+
}
254+
248255
cm := &corev1.ConfigMap{}
249-
err := r.Get(ctx, client.ObjectKey{Name: cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name, Namespace: r.GetNamespace()}, cm)
256+
err := r.Get(ctx, client.ObjectKey{Name: cmName, Namespace: r.GetNamespace()}, cm)
250257
if err != nil {
251258
return fmt.Errorf("%s: %w", utils.ErrGetProxyCACM, err)
252259
}

internal/controller/appserver/reconciler_test.go

Lines changed: 10 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: &corev1.ConfigMapKeySelector{
985+
LocalObjectReference: corev1.LocalObjectReference{
986+
Name: cmCACertName,
987+
},
986988
},
987989
}
988990
err := ReconcileAppServer(testReconcilerInstance, ctx, cr)
@@ -1008,6 +1010,12 @@ var _ = Describe("App server reconciliator", Ordered, func() {
10081010
Name: cmCACertName,
10091011
},
10101012
DefaultMode: &volumeDefaultMode,
1013+
Items: []corev1.KeyToPath{
1014+
{
1015+
Key: utils.ProxyCACertFileName,
1016+
Path: utils.ProxyCACertFileName,
1017+
},
1018+
},
10111019
},
10121020
},
10131021
},

internal/controller/lcore/config.go

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

638-
return map[string]interface{}{
638+
serviceConfig := map[string]interface{}{
639639
"host": "0.0.0.0",
640640
"port": utils.OLSAppServerContainerPort,
641641
"auth_enabled": false,
@@ -649,6 +649,28 @@ func buildLCoreServiceConfig(_ reconciler.Reconciler, cr *olsv1alpha1.OLSConfig)
649649
"tls_key_path": "/etc/certs/lightspeed-tls/tls.key",
650650
},
651651
}
652+
653+
// Add proxy configuration if specified
654+
if cr.Spec.OLSConfig.ProxyConfig != nil {
655+
proxyConfigMap := map[string]interface{}{}
656+
657+
if cr.Spec.OLSConfig.ProxyConfig.ProxyURL != "" {
658+
proxyConfigMap["proxy_url"] = cr.Spec.OLSConfig.ProxyConfig.ProxyURL
659+
}
660+
661+
proxyCACertRef := cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef
662+
cmName := utils.GetProxyCACertConfigMapName(proxyCACertRef)
663+
if cmName != "" {
664+
certKey := utils.GetProxyCACertKey(proxyCACertRef)
665+
proxyConfigMap["proxy_ca_cert_path"] = "/etc/certs/" + utils.ProxyCACertVolumeName + "/" + certKey
666+
}
667+
668+
if len(proxyConfigMap) > 0 {
669+
serviceConfig["proxy_config"] = proxyConfigMap
670+
}
671+
}
672+
673+
return serviceConfig
652674
}
653675

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

0 commit comments

Comments
 (0)