@@ -17,6 +17,8 @@ limitations under the License.
1717package v1beta1
1818
1919import (
20+ "reflect"
21+
2022 "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
2123 "github.com/openstack-k8s-operators/lib-common/modules/common/util"
2224 "k8s.io/apimachinery/pkg/api/resource"
@@ -98,6 +100,11 @@ type DatabaseSpec struct {
98100type OpenStackLightspeedSpec struct {
99101 OpenStackLightspeedCore `json:",inline"`
100102
103+ // +kubebuilder:validation:Optional
104+ // Images configures container images used by the operator.
105+ // When omitted, each image defaults to its environment variable or hardcoded fallback.
106+ Images OpenStackLightspeedImages `json:"images,omitempty"`
107+
101108 // +kubebuilder:validation:Optional
102109 // Database configures persistent storage for PostgreSQL data.
103110 // When omitted, an emptyDir volume is used (data is lost on pod reschedule).
@@ -274,42 +281,74 @@ func (instance OpenStackLightspeed) IsReady() bool {
274281 return instance .Status .Conditions .IsTrue (OpenStackLightspeedReadyCondition )
275282}
276283
284+ // OpenStackLightspeedImages groups container image URLs used by the operator.
285+ type OpenStackLightspeedImages struct {
286+ RAGImageURL string `json:"ragImage,omitempty"`
287+ LCoreImageURL string `json:"lcoreImage,omitempty"`
288+ ExporterImageURL string `json:"exporterImage,omitempty"`
289+ PostgresImageURL string `json:"postgresImage,omitempty"`
290+ ConsoleImageURL string `json:"consoleImage,omitempty"`
291+ ConsoleImagePF5URL string `json:"consoleImagePF5,omitempty"`
292+ OKPImageURL string `json:"okpImage,omitempty"`
293+ MCPServerImageURL string `json:"mcpServerImage,omitempty"`
294+ }
295+
277296type OpenStackLightspeedDefaults struct {
278- RAGImageURL string
279- LCoreImageURL string
280- ExporterImageURL string
281- PostgresImageURL string
282- ConsoleImageURL string
283- ConsoleImagePF5URL string
284- OKPImageURL string
285- MCPServerImageURL string
286- MaxTokensForResponse int
297+ OpenStackLightspeedImages `json:",inline"`
298+ MaxTokensForResponse int `json:"maxTokensForResponse,omitempty"`
287299}
288300
289301var OpenStackLightspeedDefaultValues OpenStackLightspeedDefaults
290302
291- // SetupDefaults - initializes OpenStackLightspeedDefaultValues with default values from env vars
303+ // envVarDefaults holds the pristine env-var defaults set once by SetupDefaults.
304+ // MergeDefaults copies from this so that removing dev overrides correctly
305+ // reverts to the original values (the exported global gets overwritten each reconcile).
306+ var envVarDefaults OpenStackLightspeedDefaults
307+
308+ // mergeImages applies non-zero fields from src onto dst.
309+ func mergeImages (dst , src * OpenStackLightspeedImages ) {
310+ dstVal := reflect .ValueOf (dst ).Elem ()
311+ srcVal := reflect .ValueOf (src ).Elem ()
312+ for i := 0 ; i < srcVal .NumField (); i ++ {
313+ if ! srcVal .Field (i ).IsZero () {
314+ dstVal .Field (i ).Set (srcVal .Field (i ))
315+ }
316+ }
317+ }
318+
319+ // SetupDefaults initializes OpenStackLightspeedDefaultValues from env vars.
320+ // Call once at startup; the values never change inside a container.
292321func SetupDefaults () {
293- // Acquire environmental defaults and initialize OpenStackLightspeed defaults with them
294- openStackLightspeedDefaults := OpenStackLightspeedDefaults {
295- RAGImageURL : util .GetEnvVar (
296- "RELATED_IMAGE_OPENSTACK_LIGHTSPEED_IMAGE_URL_DEFAULT" , OpenStackLightspeedContainerImage ),
297- LCoreImageURL : util .GetEnvVar (
298- "RELATED_IMAGE_LCORE_IMAGE_URL_DEFAULT" , LCoreContainerImage ),
299- ExporterImageURL : util .GetEnvVar (
300- "RELATED_IMAGE_EXPORTER_IMAGE_URL_DEFAULT" , ExporterContainerImage ),
301- PostgresImageURL : util .GetEnvVar (
302- "RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT" , PostgresContainerImage ),
303- ConsoleImageURL : util .GetEnvVar (
304- "RELATED_IMAGE_CONSOLE_IMAGE_URL_DEFAULT" , ConsoleContainerImage ),
305- ConsoleImagePF5URL : util .GetEnvVar (
306- "RELATED_IMAGE_CONSOLE_PF5_IMAGE_URL_DEFAULT" , ConsoleContainerImagePF5 ),
307- OKPImageURL : util .GetEnvVar (
308- "RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT" , OKPContainerImage ),
309- MCPServerImageURL : util .GetEnvVar (
310- "RELATED_IMAGE_MCP_SERVER_IMAGE_URL_DEFAULT" , MCPServerContainerImage ),
322+ envVarDefaults = OpenStackLightspeedDefaults {
323+ OpenStackLightspeedImages : OpenStackLightspeedImages {
324+ RAGImageURL : util .GetEnvVar (
325+ "RELATED_IMAGE_OPENSTACK_LIGHTSPEED_IMAGE_URL_DEFAULT" , OpenStackLightspeedContainerImage ),
326+ LCoreImageURL : util .GetEnvVar (
327+ "RELATED_IMAGE_LCORE_IMAGE_URL_DEFAULT" , LCoreContainerImage ),
328+ ExporterImageURL : util .GetEnvVar (
329+ "RELATED_IMAGE_EXPORTER_IMAGE_URL_DEFAULT" , ExporterContainerImage ),
330+ PostgresImageURL : util .GetEnvVar (
331+ "RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT" , PostgresContainerImage ),
332+ ConsoleImageURL : util .GetEnvVar (
333+ "RELATED_IMAGE_CONSOLE_IMAGE_URL_DEFAULT" , ConsoleContainerImage ),
334+ ConsoleImagePF5URL : util .GetEnvVar (
335+ "RELATED_IMAGE_CONSOLE_PF5_IMAGE_URL_DEFAULT" , ConsoleContainerImagePF5 ),
336+ OKPImageURL : util .GetEnvVar (
337+ "RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT" , OKPContainerImage ),
338+ MCPServerImageURL : util .GetEnvVar (
339+ "RELATED_IMAGE_MCP_SERVER_IMAGE_URL_DEFAULT" , MCPServerContainerImage ),
340+ },
311341 MaxTokensForResponse : MaxTokensForResponseDefault ,
312342 }
343+ OpenStackLightspeedDefaultValues = envVarDefaults
344+ }
313345
314- OpenStackLightspeedDefaultValues = openStackLightspeedDefaults
346+ // MergeDefaults returns a copy of the env-var defaults with the spec image
347+ // overrides (if any) applied on top.
348+ func MergeDefaults (specImages * OpenStackLightspeedImages ) OpenStackLightspeedDefaults {
349+ merged := envVarDefaults
350+ if specImages != nil {
351+ mergeImages (& merged .OpenStackLightspeedImages , specImages )
352+ }
353+ return merged
315354}
0 commit comments