@@ -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).
@@ -271,42 +278,74 @@ func (instance OpenStackLightspeed) IsReady() bool {
271278 return instance .Status .Conditions .IsTrue (OpenStackLightspeedReadyCondition )
272279}
273280
281+ // OpenStackLightspeedImages groups container image URLs used by the operator.
282+ type OpenStackLightspeedImages struct {
283+ RAGImageURL string `json:"ragImage,omitempty"`
284+ LCoreImageURL string `json:"lcoreImage,omitempty"`
285+ ExporterImageURL string `json:"exporterImage,omitempty"`
286+ PostgresImageURL string `json:"postgresImage,omitempty"`
287+ ConsoleImageURL string `json:"consoleImage,omitempty"`
288+ ConsoleImagePF5URL string `json:"consoleImagePF5,omitempty"`
289+ OKPImageURL string `json:"okpImage,omitempty"`
290+ MCPServerImageURL string `json:"mcpServerImage,omitempty"`
291+ }
292+
274293type OpenStackLightspeedDefaults struct {
275- RAGImageURL string
276- LCoreImageURL string
277- ExporterImageURL string
278- PostgresImageURL string
279- ConsoleImageURL string
280- ConsoleImagePF5URL string
281- OKPImageURL string
282- MCPServerImageURL string
283- MaxTokensForResponse int
294+ OpenStackLightspeedImages `json:",inline"`
295+ MaxTokensForResponse int `json:"maxTokensForResponse,omitempty"`
284296}
285297
286298var OpenStackLightspeedDefaultValues OpenStackLightspeedDefaults
287299
288- // SetupDefaults - initializes OpenStackLightspeedDefaultValues with default values from env vars
300+ // envVarDefaults holds the pristine env-var defaults set once by SetupDefaults.
301+ // MergeDefaults copies from this so that removing dev overrides correctly
302+ // reverts to the original values (the exported global gets overwritten each reconcile).
303+ var envVarDefaults OpenStackLightspeedDefaults
304+
305+ // mergeImages applies non-zero fields from src onto dst.
306+ func mergeImages (dst , src * OpenStackLightspeedImages ) {
307+ dstVal := reflect .ValueOf (dst ).Elem ()
308+ srcVal := reflect .ValueOf (src ).Elem ()
309+ for i := 0 ; i < srcVal .NumField (); i ++ {
310+ if ! srcVal .Field (i ).IsZero () {
311+ dstVal .Field (i ).Set (srcVal .Field (i ))
312+ }
313+ }
314+ }
315+
316+ // SetupDefaults initializes OpenStackLightspeedDefaultValues from env vars.
317+ // Call once at startup; the values never change inside a container.
289318func SetupDefaults () {
290- // Acquire environmental defaults and initialize OpenStackLightspeed defaults with them
291- openStackLightspeedDefaults := OpenStackLightspeedDefaults {
292- RAGImageURL : util .GetEnvVar (
293- "RELATED_IMAGE_OPENSTACK_LIGHTSPEED_IMAGE_URL_DEFAULT" , OpenStackLightspeedContainerImage ),
294- LCoreImageURL : util .GetEnvVar (
295- "RELATED_IMAGE_LCORE_IMAGE_URL_DEFAULT" , LCoreContainerImage ),
296- ExporterImageURL : util .GetEnvVar (
297- "RELATED_IMAGE_EXPORTER_IMAGE_URL_DEFAULT" , ExporterContainerImage ),
298- PostgresImageURL : util .GetEnvVar (
299- "RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT" , PostgresContainerImage ),
300- ConsoleImageURL : util .GetEnvVar (
301- "RELATED_IMAGE_CONSOLE_IMAGE_URL_DEFAULT" , ConsoleContainerImage ),
302- ConsoleImagePF5URL : util .GetEnvVar (
303- "RELATED_IMAGE_CONSOLE_PF5_IMAGE_URL_DEFAULT" , ConsoleContainerImagePF5 ),
304- OKPImageURL : util .GetEnvVar (
305- "RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT" , OKPContainerImage ),
306- MCPServerImageURL : util .GetEnvVar (
307- "RELATED_IMAGE_MCP_SERVER_IMAGE_URL_DEFAULT" , MCPServerContainerImage ),
319+ envVarDefaults = OpenStackLightspeedDefaults {
320+ OpenStackLightspeedImages : OpenStackLightspeedImages {
321+ RAGImageURL : util .GetEnvVar (
322+ "RELATED_IMAGE_OPENSTACK_LIGHTSPEED_IMAGE_URL_DEFAULT" , OpenStackLightspeedContainerImage ),
323+ LCoreImageURL : util .GetEnvVar (
324+ "RELATED_IMAGE_LCORE_IMAGE_URL_DEFAULT" , LCoreContainerImage ),
325+ ExporterImageURL : util .GetEnvVar (
326+ "RELATED_IMAGE_EXPORTER_IMAGE_URL_DEFAULT" , ExporterContainerImage ),
327+ PostgresImageURL : util .GetEnvVar (
328+ "RELATED_IMAGE_POSTGRES_IMAGE_URL_DEFAULT" , PostgresContainerImage ),
329+ ConsoleImageURL : util .GetEnvVar (
330+ "RELATED_IMAGE_CONSOLE_IMAGE_URL_DEFAULT" , ConsoleContainerImage ),
331+ ConsoleImagePF5URL : util .GetEnvVar (
332+ "RELATED_IMAGE_CONSOLE_PF5_IMAGE_URL_DEFAULT" , ConsoleContainerImagePF5 ),
333+ OKPImageURL : util .GetEnvVar (
334+ "RELATED_IMAGE_OKP_IMAGE_URL_DEFAULT" , OKPContainerImage ),
335+ MCPServerImageURL : util .GetEnvVar (
336+ "RELATED_IMAGE_MCP_SERVER_IMAGE_URL_DEFAULT" , MCPServerContainerImage ),
337+ },
308338 MaxTokensForResponse : MaxTokensForResponseDefault ,
309339 }
340+ OpenStackLightspeedDefaultValues = envVarDefaults
341+ }
310342
311- OpenStackLightspeedDefaultValues = openStackLightspeedDefaults
343+ // MergeDefaults returns a copy of the env-var defaults with the spec image
344+ // overrides (if any) applied on top.
345+ func MergeDefaults (specImages * OpenStackLightspeedImages ) OpenStackLightspeedDefaults {
346+ merged := envVarDefaults
347+ if specImages != nil {
348+ mergeImages (& merged .OpenStackLightspeedImages , specImages )
349+ }
350+ return merged
312351}
0 commit comments