Skip to content

Commit 6c59395

Browse files
committed
feat: External ConfigMap Support for Cross-Operator Integration.
1 parent 5bca8b0 commit 6c59395

File tree

5 files changed

+170
-0
lines changed

5 files changed

+170
-0
lines changed

api/v1alpha1/llamastackdistribution_types.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/llamastack.io_llamastackdistributions.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,31 @@ spec:
263263
x-kubernetes-validations:
264264
- message: Only one of name or image can be specified
265265
rule: '!(has(self.name) && has(self.image))'
266+
envFromExternalConfigMaps:
267+
description: EnvFromExternalConfigMaps defines external ConfigMaps
268+
to inject as environment variables
269+
items:
270+
description: ExternalConfigMapSpec defines external ConfigMaps
271+
to inject as environment variables
272+
properties:
273+
mapping:
274+
additionalProperties:
275+
type: string
276+
description: |-
277+
Mapping defines how ConfigMap keys map to environment variable names
278+
Key is the ConfigMap key, Value is the environment variable name
279+
type: object
280+
name:
281+
description: Name is the name of the ConfigMap
282+
type: string
283+
namespace:
284+
description: Namespace is the namespace of the ConfigMap
285+
type: string
286+
required:
287+
- name
288+
- namespace
289+
type: object
290+
type: array
266291
podOverrides:
267292
description: PodOverrides allows advanced pod-level customization.
268293
properties:
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
apiVersion: llamastack.io/v1alpha1
2+
kind: LlamaStackDistribution
3+
metadata:
4+
name: llamastackdistribution-with-external-configmaps
5+
spec:
6+
replicas: 1
7+
server:
8+
containerSpec:
9+
env:
10+
- name: INFERENCE_MODEL
11+
value: 'llama3.2:1b'
12+
- name: OLLAMA_URL
13+
value: 'http://ollama-server-service.ollama-dist.svc.cluster.local:11434'
14+
name: llama-stack
15+
distribution:
16+
name: starter
17+
storage:
18+
size: "20Gi"
19+
mountPath: "/home/lls/.lls"
20+
# External ConfigMaps configuration - enables referencing Konflux-built images
21+
# from the redhat-ods-applications namespace ConfigMaps
22+
envFromExternalConfigMaps:
23+
- name: trustyai-service-operator-config
24+
namespace: redhat-ods-applications
25+
mapping:
26+
ragas-provider-image: RAGAS_PROVIDER_IMAGE
27+
garak-provider-image: GARAK_PROVIDER_IMAGE
28+
---
29+
# Example of how the ConfigMap would look like in redhat-ods-applications namespace
30+
# This would be automatically created/managed by the trustyai-service-operator
31+
apiVersion: v1
32+
kind: ConfigMap
33+
metadata:
34+
name: trustyai-service-operator-config
35+
namespace: redhat-ods-applications
36+
data:
37+
ragas-provider-image: "quay.io/trustyai/llama-stack-provider-ragas:v1.2.3-konflux-build-123"
38+
garak-provider-image: "quay.io/trustyai/llama-stack-provider-trustyai-garak:v1.2.3-konflux-build-456"
39+
# Other trustyai operator configuration values...
40+
trustyaiServiceImage: "quay.io/trustyai/trustyai-service:latest"
41+
trustyaiOperatorImage: "quay.io/trustyai/trustyai-service-operator:latest"

controllers/resource_helper.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import (
2525

2626
llamav1alpha1 "github.com/llamastack/llama-stack-k8s-operator/api/v1alpha1"
2727
corev1 "k8s.io/api/core/v1"
28+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
29+
"k8s.io/apimachinery/pkg/types"
2830
"k8s.io/apimachinery/pkg/util/intstr"
2931
"k8s.io/utils/ptr"
3032
"sigs.k8s.io/controller-runtime/pkg/log"
@@ -186,6 +188,13 @@ func configureContainerEnvironment(ctx context.Context, r *LlamaStackDistributio
186188
}
187189
}
188190

191+
// Add environment variables from external ConfigMaps
192+
if err := addExternalConfigMapEnvVars(ctx, r, instance, container); err != nil {
193+
// Log error but don't fail deployment - allows graceful degradation
194+
logger := log.FromContext(ctx)
195+
logger.Error(err, "Failed to add external ConfigMap environment variables")
196+
}
197+
189198
// Finally, add the user provided env vars
190199
container.Env = append(container.Env, instance.Spec.Server.ContainerSpec.Env...)
191200
}
@@ -662,3 +671,54 @@ func (r *LlamaStackDistributionReconciler) resolveImage(distribution llamav1alph
662671
return "", errors.New("failed to validate distribution: either distribution.name or distribution.image must be set")
663672
}
664673
}
674+
675+
// addExternalConfigMapEnvVars adds environment variables from external ConfigMaps
676+
func addExternalConfigMapEnvVars(ctx context.Context, r *LlamaStackDistributionReconciler, instance *llamav1alpha1.LlamaStackDistribution, container *corev1.Container) error {
677+
if len(instance.Spec.Server.EnvFromExternalConfigMaps) == 0 {
678+
return nil
679+
}
680+
681+
logger := log.FromContext(ctx)
682+
683+
for _, extConfigMap := range instance.Spec.Server.EnvFromExternalConfigMaps {
684+
// Fetch the external ConfigMap
685+
configMap := &corev1.ConfigMap{}
686+
err := r.Get(ctx, types.NamespacedName{
687+
Name: extConfigMap.Name,
688+
Namespace: extConfigMap.Namespace,
689+
}, configMap)
690+
691+
if err != nil {
692+
if k8serrors.IsNotFound(err) {
693+
logger.Info("External ConfigMap not found, skipping",
694+
"configMapName", extConfigMap.Name,
695+
"configMapNamespace", extConfigMap.Namespace)
696+
continue
697+
}
698+
return fmt.Errorf("failed to get external ConfigMap %s/%s: %w",
699+
extConfigMap.Namespace, extConfigMap.Name, err)
700+
}
701+
702+
// Process the mapping and add environment variables
703+
for configMapKey, envVarName := range extConfigMap.Mapping {
704+
if value, exists := configMap.Data[configMapKey]; exists {
705+
container.Env = append(container.Env, corev1.EnvVar{
706+
Name: envVarName,
707+
Value: value,
708+
})
709+
logger.V(1).Info("Added environment variable from external ConfigMap",
710+
"configMapName", extConfigMap.Name,
711+
"configMapNamespace", extConfigMap.Namespace,
712+
"configMapKey", configMapKey,
713+
"envVarName", envVarName)
714+
} else {
715+
logger.Info("ConfigMap key not found, skipping",
716+
"configMapName", extConfigMap.Name,
717+
"configMapNamespace", extConfigMap.Namespace,
718+
"configMapKey", configMapKey)
719+
}
720+
}
721+
}
722+
723+
return nil
724+
}

0 commit comments

Comments
 (0)