diff --git a/examples/operator-quickstart/feast.yaml b/examples/operator-quickstart/feast.yaml index def24bd9a4..d1d7e4df86 100644 --- a/examples/operator-quickstart/feast.yaml +++ b/examples/operator-quickstart/feast.yaml @@ -25,18 +25,12 @@ spec: persistence: file: type: duckdb - envFrom: - - secretRef: - name: postgres-secret onlineStore: persistence: store: type: redis secretRef: name: feast-data-stores - envFrom: - - secretRef: - name: postgres-secret registry: local: persistence: @@ -44,13 +38,14 @@ spec: type: sql secretRef: name: feast-data-stores - envFrom: - - secretRef: - name: postgres-secret - env: - - name: MPLCONFIGDIR - value: /tmp - resources: - requests: - cpu: 150m - memory: 128Mi + server: + envFrom: + - secretRef: + name: postgres-secret + env: + - name: MPLCONFIGDIR + value: /tmp + resources: + requests: + cpu: 150m + memory: 128Mi diff --git a/infra/feast-operator/api/v1alpha1/featurestore_types.go b/infra/feast-operator/api/v1alpha1/featurestore_types.go index 19b13be8c5..845b265727 100644 --- a/infra/feast-operator/api/v1alpha1/featurestore_types.go +++ b/infra/feast-operator/api/v1alpha1/featurestore_types.go @@ -73,9 +73,10 @@ type FeatureStoreSpec struct { // FeatureStoreServices defines the desired feast services. An ephemeral registry is deployed by default. type FeatureStoreServices struct { - OfflineStore *OfflineStore `json:"offlineStore,omitempty"` - OnlineStore *OnlineStore `json:"onlineStore,omitempty"` - Registry *Registry `json:"registry,omitempty"` + OfflineStore *OfflineStore `json:"offlineStore,omitempty"` + OnlineStore *OnlineStore `json:"onlineStore,omitempty"` + Registry *Registry `json:"registry,omitempty"` + // Creates a UI server container UI *ServerConfigs `json:"ui,omitempty"` DeploymentStrategy *appsv1.DeploymentStrategy `json:"deploymentStrategy,omitempty"` // Disable the 'feast repo initialization' initContainer @@ -84,8 +85,9 @@ type FeatureStoreServices struct { // OfflineStore configures the deployed offline store service type OfflineStore struct { - ServerConfigs `json:",inline"` - Persistence *OfflineStorePersistence `json:"persistence,omitempty"` + // Creates a remote offline server container + Server *ServerConfigs `json:"server,omitempty"` + Persistence *OfflineStorePersistence `json:"persistence,omitempty"` } // OfflineStorePersistence configures the persistence settings for the offline store service @@ -132,8 +134,9 @@ var ValidOfflineStoreDBStorePersistenceTypes = []string{ // OnlineStore configures the deployed online store service type OnlineStore struct { - ServerConfigs `json:",inline"` - Persistence *OnlineStorePersistence `json:"persistence,omitempty"` + // Creates a feature server container + Server *ServerConfigs `json:"server,omitempty"` + Persistence *OnlineStorePersistence `json:"persistence,omitempty"` } // OnlineStorePersistence configures the persistence settings for the online store service @@ -183,8 +186,9 @@ var ValidOnlineStoreDBStorePersistenceTypes = []string{ // LocalRegistryConfig configures the deployed registry service type LocalRegistryConfig struct { - ServerConfigs `json:",inline"` - Persistence *RegistryPersistence `json:"persistence,omitempty"` + // Creates a registry server container + Server *ServerConfigs `json:"server,omitempty"` + Persistence *RegistryPersistence `json:"persistence,omitempty"` } // RegistryPersistence configures the persistence settings for the registry service @@ -277,14 +281,14 @@ type FeatureStoreRef struct { Namespace string `json:"namespace,omitempty"` } -// ServerConfigs server-related configurations for a feast service +// ServerConfigs creates a server for the feast service, with specified container configurations. type ServerConfigs struct { ContainerConfigs `json:",inline"` TLS *TlsConfigs `json:"tls,omitempty"` // LogLevel sets the logging level for the server // Allowed values: "debug", "info", "warning", "error", "critical". // +kubebuilder:validation:Enum=debug;info;warning;error;critical - LogLevel string `json:"logLevel,omitempty"` + LogLevel *string `json:"logLevel,omitempty"` } // ContainerConfigs k8s container settings for the server diff --git a/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go b/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go index cb5a4eb34b..36f5bd3397 100644 --- a/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -275,7 +275,11 @@ func (in *KubernetesAuthz) DeepCopy() *KubernetesAuthz { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalRegistryConfig) DeepCopyInto(out *LocalRegistryConfig) { *out = *in - in.ServerConfigs.DeepCopyInto(&out.ServerConfigs) + if in.Server != nil { + in, out := &in.Server, &out.Server + *out = new(ServerConfigs) + (*in).DeepCopyInto(*out) + } if in.Persistence != nil { in, out := &in.Persistence, &out.Persistence *out = new(RegistryPersistence) @@ -296,7 +300,11 @@ func (in *LocalRegistryConfig) DeepCopy() *LocalRegistryConfig { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OfflineStore) DeepCopyInto(out *OfflineStore) { *out = *in - in.ServerConfigs.DeepCopyInto(&out.ServerConfigs) + if in.Server != nil { + in, out := &in.Server, &out.Server + *out = new(ServerConfigs) + (*in).DeepCopyInto(*out) + } if in.Persistence != nil { in, out := &in.Persistence, &out.Persistence *out = new(OfflineStorePersistence) @@ -394,7 +402,11 @@ func (in *OidcAuthz) DeepCopy() *OidcAuthz { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OnlineStore) DeepCopyInto(out *OnlineStore) { *out = *in - in.ServerConfigs.DeepCopyInto(&out.ServerConfigs) + if in.Server != nil { + in, out := &in.Server, &out.Server + *out = new(ServerConfigs) + (*in).DeepCopyInto(*out) + } if in.Persistence != nil { in, out := &in.Persistence, &out.Persistence *out = new(OnlineStorePersistence) @@ -722,6 +734,11 @@ func (in *ServerConfigs) DeepCopyInto(out *ServerConfigs) { *out = new(TlsConfigs) (*in).DeepCopyInto(*out) } + if in.LogLevel != nil { + in, out := &in.LogLevel, &out.LogLevel + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerConfigs. diff --git a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml index 81f8ee310d..6344896fb8 100644 --- a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml +++ b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml @@ -87,109 +87,6 @@ spec: type: boolean offlineStore: properties: - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string persistence: properties: file: @@ -285,166 +182,169 @@ spec: x-kubernetes-validations: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: + server: properties: - claims: + env: items: properties: name: type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object required: - name type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - type: object - onlineStore: - properties: - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: + envFrom: + items: properties: - configMapKeyRef: + configMapRef: properties: - key: - type: string name: default: "" type: string optional: type: boolean - required: - - key type: object x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: + prefix: + type: string + secretRef: properties: - key: - type: string name: default: "" type: string optional: type: boolean - required: - - key type: object x-kubernetes-map-type: atomic type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string + type: array + image: + type: string + imagePullPolicy: + type: string + logLevel: + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + tls: + properties: + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + type: object + type: object + onlineStore: + properties: persistence: properties: file: @@ -522,96 +422,39 @@ spec: type: string secretRef: properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - type: - enum: - - snowflake.online - - redis - - ikv - - datastore - - dynamodb - - bigtable - - postgres - - cassandra - - mysql - - hazelcast - - singlestore - - hbase - - elasticsearch - - qdrant - - couchbase - - milvus - type: string - required: - - secretRef - - type - type: object - type: object - x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: - properties: - claims: - items: - properties: - name: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: + enum: + - snowflake.online + - redis + - ikv + - datastore + - dynamodb + - bigtable + - postgres + - cassandra + - mysql + - hazelcast + - singlestore + - hbase + - elasticsearch + - qdrant + - couchbase + - milvus type: string + required: + - secretRef + - type type: object - x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - type: object - registry: - properties: - local: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, c)' + server: properties: env: items: @@ -716,6 +559,66 @@ spec: - error - critical type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + tls: + properties: + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + type: object + type: object + registry: + properties: + local: + properties: persistence: properties: file: @@ -767,42 +670,210 @@ spec: required: - mountPath type: object - x-kubernetes-validations: - - message: One selection is required between ref - and create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' and - must not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - s3_additional_kwargs: + x-kubernetes-validations: + - message: One selection is required between ref + and create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' and + must not contain ':' + rule: self.mountPath.matches('^/[^:]*$') + s3_additional_kwargs: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-validations: + - message: Registry files must use absolute paths + or be S3 ('s3://') or GS ('gs://') object store + URIs. + rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') + || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) + : true' + - message: PVC path must be a file name only, with + no slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: PVC persistence does not support S3 or + GS object store URIs. + rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + - message: Additional S3 settings are available only + for S3 object store URIs. + rule: '(has(self.s3_additional_kwargs) && has(self.path)) + ? self.path.startsWith(''s3://'') : true' + store: + properties: + secretKeyName: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: + enum: + - sql + - snowflake.registry + type: string + required: + - secretRef + - type + type: object + type: object + x-kubernetes-validations: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, + c)' + server: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + logLevel: + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: additionalProperties: - type: string + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true type: object type: object - x-kubernetes-validations: - - message: Registry files must use absolute paths - or be S3 ('s3://') or GS ('gs://') object store - URIs. - rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') - || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) - : true' - - message: PVC path must be a file name only, with - no slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: PVC persistence does not support S3 or - GS object store URIs. - rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - - message: Additional S3 settings are available only - for S3 object store URIs. - rule: '(has(self.s3_additional_kwargs) && has(self.path)) - ? self.path.startsWith(''s3://'') : true' - store: + tls: properties: - secretKeyName: - type: string + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object secretRef: properties: name: @@ -810,74 +881,12 @@ spec: type: string type: object x-kubernetes-map-type: atomic - type: - enum: - - sql - - snowflake.registry - type: string - required: - - secretRef - - type - type: object - type: object - x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, - c)' - resources: - properties: - claims: - items: - properties: - name: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" - type: string type: object - x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' type: object remote: properties: @@ -1124,122 +1133,19 @@ spec: - type: integer - type: string x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - type: object - type: - type: string - type: object - disableInitContainers: - type: boolean - offlineStore: - properties: - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: type: string + type: object + disableInitContainers: + type: boolean + offlineStore: + properties: persistence: properties: file: @@ -1336,166 +1242,169 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: + server: properties: - claims: + env: items: properties: name: type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object required: - name type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - type: object - onlineStore: - properties: - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: + envFrom: + items: properties: - configMapKeyRef: + configMapRef: properties: - key: - type: string name: default: "" type: string optional: type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource type: object x-kubernetes-map-type: atomic - secretKeyRef: + prefix: + type: string + secretRef: properties: - key: - type: string name: default: "" type: string optional: type: boolean - required: - - key type: object x-kubernetes-map-type: atomic type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string + type: array + image: + type: string + imagePullPolicy: + type: string + logLevel: + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + tls: + properties: + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + type: object + type: object + onlineStore: + properties: persistence: properties: file: @@ -1607,64 +1516,7 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: - properties: - claims: - items: - properties: - name: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - type: object - registry: - properties: - local: + server: properties: env: items: @@ -1769,6 +1621,66 @@ spec: - error - critical type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + tls: + properties: + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + type: object + type: object + registry: + properties: + local: + properties: persistence: properties: file: @@ -1878,60 +1790,167 @@ spec: store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: + server: properties: - claims: + env: items: properties: name: type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object required: - name type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + logLevel: + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: properties: - tlsCrt: - type: string - tlsKey: - type: string + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object type: object - secretRef: + tls: properties: - name: - default: "" - type: string + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic type: object - x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: '`secretRef` required if `disable` + is false.' + rule: '(!has(self.disable) || !self.disable) + ? has(self.secretRef) : true' type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' type: object remote: properties: diff --git a/infra/feast-operator/config/samples/kustomization.yaml b/infra/feast-operator/config/samples/kustomization.yaml index 35eb822651..ecb2e09c95 100644 --- a/infra/feast-operator/config/samples/kustomization.yaml +++ b/infra/feast-operator/config/samples/kustomization.yaml @@ -1,5 +1,5 @@ ## Append samples of your project ## resources: - v1alpha1_featurestore.yaml -- v1alpha1_featurestore_all_services_default.yaml +- v1alpha1_featurestore_all_servers.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_all_services_default.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_all_servers.yaml similarity index 53% rename from infra/feast-operator/config/samples/v1alpha1_featurestore_all_services_default.yaml rename to infra/feast-operator/config/samples/v1alpha1_featurestore_all_servers.yaml index 1eef0874ff..ccaeb31db2 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_all_services_default.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_all_servers.yaml @@ -1,12 +1,12 @@ apiVersion: feast.dev/v1alpha1 kind: FeatureStore metadata: - name: sample-all-services + name: sample-all-servers spec: feastProject: my_project services: - onlineStore: {} - offlineStore: {} + onlineStore: + server: {} + offlineStore: + server: {} ui: {} - registry: - local: {} diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_db_persistence.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_db_persistence.yaml index eaeca89349..bcecc33a3e 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_db_persistence.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_db_persistence.yaml @@ -16,7 +16,7 @@ metadata: name: feast-data-stores namespace: test stringData: - postgres-secret-parameters: | + sql: | path: postgresql+psycopg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres.test.svc.cluster.local:5432/${POSTGRES_DB} cache_ttl_seconds: 60 sqlalchemy_config_kwargs: @@ -44,9 +44,6 @@ spec: type: postgres secretRef: name: feast-data-stores - envFrom: - - secretRef: - name: postgres-secret registry: local: persistence: @@ -54,7 +51,7 @@ spec: type: sql secretRef: name: feast-data-stores - secretKeyName: postgres-secret-parameters # optional, will use store.type by default as the SecretKeyName if none is specified, in this case that's "sql" - envFrom: - - secretRef: - name: postgres-secret + server: + envFrom: + - secretRef: + name: postgres-secret diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_openshift_tls_disable.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_openshift_tls_disable.yaml index 2389356be7..7b9c581964 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_openshift_tls_disable.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_openshift_tls_disable.yaml @@ -7,15 +7,18 @@ spec: feastProject: my_project services: onlineStore: - tls: - disable : true + server: + tls: + disable: true offlineStore: - tls: - disable: true + server: + tls: + disable: true + registry: + local: + server: + tls: + disable: true ui: tls: disable: true - registry: - local: - tls: - disable: true diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_services_loglevel.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_services_loglevel.yaml index 1291ea7dfa..e738e6352b 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_services_loglevel.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_services_loglevel.yaml @@ -6,12 +6,14 @@ spec: feastProject: my_project services: onlineStore: - logLevel: debug + server: + logLevel: debug offlineStore: - logLevel: debug - ui: - logLevel: debug + server: + logLevel: debug registry: local: - logLevel: info - + server: + logLevel: debug + ui: + logLevel: debug diff --git a/infra/feast-operator/dist/install.yaml b/infra/feast-operator/dist/install.yaml index 2ef2845475..62f8c2fe16 100644 --- a/infra/feast-operator/dist/install.yaml +++ b/infra/feast-operator/dist/install.yaml @@ -95,109 +95,6 @@ spec: type: boolean offlineStore: properties: - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string persistence: properties: file: @@ -293,166 +190,169 @@ spec: x-kubernetes-validations: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: + server: properties: - claims: + env: items: properties: name: type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object required: - name type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - type: object - onlineStore: - properties: - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: + envFrom: + items: properties: - configMapKeyRef: + configMapRef: properties: - key: - type: string name: default: "" type: string optional: type: boolean - required: - - key type: object x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: + prefix: + type: string + secretRef: properties: - key: - type: string name: default: "" type: string optional: type: boolean - required: - - key type: object x-kubernetes-map-type: atomic type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string + type: array + image: + type: string + imagePullPolicy: + type: string + logLevel: + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + tls: + properties: + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + type: object + type: object + onlineStore: + properties: persistence: properties: file: @@ -530,96 +430,39 @@ spec: type: string secretRef: properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - type: - enum: - - snowflake.online - - redis - - ikv - - datastore - - dynamodb - - bigtable - - postgres - - cassandra - - mysql - - hazelcast - - singlestore - - hbase - - elasticsearch - - qdrant - - couchbase - - milvus - type: string - required: - - secretRef - - type - type: object - type: object - x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: - properties: - claims: - items: - properties: - name: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: + enum: + - snowflake.online + - redis + - ikv + - datastore + - dynamodb + - bigtable + - postgres + - cassandra + - mysql + - hazelcast + - singlestore + - hbase + - elasticsearch + - qdrant + - couchbase + - milvus type: string + required: + - secretRef + - type type: object - x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - type: object - registry: - properties: - local: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, c)' + server: properties: env: items: @@ -724,6 +567,66 @@ spec: - error - critical type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + tls: + properties: + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + type: object + type: object + registry: + properties: + local: + properties: persistence: properties: file: @@ -775,42 +678,210 @@ spec: required: - mountPath type: object - x-kubernetes-validations: - - message: One selection is required between ref - and create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' and - must not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - s3_additional_kwargs: + x-kubernetes-validations: + - message: One selection is required between ref + and create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' and + must not contain ':' + rule: self.mountPath.matches('^/[^:]*$') + s3_additional_kwargs: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-validations: + - message: Registry files must use absolute paths + or be S3 ('s3://') or GS ('gs://') object store + URIs. + rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') + || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) + : true' + - message: PVC path must be a file name only, with + no slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: PVC persistence does not support S3 or + GS object store URIs. + rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + - message: Additional S3 settings are available only + for S3 object store URIs. + rule: '(has(self.s3_additional_kwargs) && has(self.path)) + ? self.path.startsWith(''s3://'') : true' + store: + properties: + secretKeyName: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: + enum: + - sql + - snowflake.registry + type: string + required: + - secretRef + - type + type: object + type: object + x-kubernetes-validations: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, + c)' + server: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + logLevel: + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: additionalProperties: - type: string + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true type: object type: object - x-kubernetes-validations: - - message: Registry files must use absolute paths - or be S3 ('s3://') or GS ('gs://') object store - URIs. - rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') - || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) - : true' - - message: PVC path must be a file name only, with - no slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: PVC persistence does not support S3 or - GS object store URIs. - rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - - message: Additional S3 settings are available only - for S3 object store URIs. - rule: '(has(self.s3_additional_kwargs) && has(self.path)) - ? self.path.startsWith(''s3://'') : true' - store: + tls: properties: - secretKeyName: - type: string + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object secretRef: properties: name: @@ -818,74 +889,12 @@ spec: type: string type: object x-kubernetes-map-type: atomic - type: - enum: - - sql - - snowflake.registry - type: string - required: - - secretRef - - type - type: object - type: object - x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, - c)' - resources: - properties: - claims: - items: - properties: - name: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" - type: string type: object - x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' type: object remote: properties: @@ -1132,122 +1141,19 @@ spec: - type: integer - type: string x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - type: object - type: - type: string - type: object - disableInitContainers: - type: boolean - offlineStore: - properties: - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + type: type: string + type: object + disableInitContainers: + type: boolean + offlineStore: + properties: persistence: properties: file: @@ -1344,166 +1250,169 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: + server: properties: - claims: + env: items: properties: name: type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object required: - name type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - type: object - onlineStore: - properties: - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: + envFrom: + items: properties: - configMapKeyRef: + configMapRef: properties: - key: - type: string name: default: "" type: string optional: type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource type: object x-kubernetes-map-type: atomic - secretKeyRef: + prefix: + type: string + secretRef: properties: - key: - type: string name: default: "" type: string optional: type: boolean - required: - - key type: object x-kubernetes-map-type: atomic type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string + type: array + image: + type: string + imagePullPolicy: + type: string + logLevel: + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + tls: + properties: + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + type: object + type: object + onlineStore: + properties: persistence: properties: file: @@ -1615,64 +1524,7 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: - properties: - claims: - items: - properties: - name: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: - properties: - tlsCrt: - type: string - tlsKey: - type: string - type: object - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - type: object - registry: - properties: - local: + server: properties: env: items: @@ -1777,6 +1629,66 @@ spec: - error - critical type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + tls: + properties: + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + type: object + type: object + registry: + properties: + local: + properties: persistence: properties: file: @@ -1886,60 +1798,167 @@ spec: store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: + server: properties: - claims: + env: items: properties: name: type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object required: - name type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - tls: - properties: - disable: - type: boolean - secretKeyNames: + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + logLevel: + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: properties: - tlsCrt: - type: string - tlsKey: - type: string + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object type: object - secretRef: + tls: properties: - name: - default: "" - type: string + disable: + type: boolean + secretKeyNames: + properties: + tlsCrt: + type: string + tlsKey: + type: string + type: object + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic type: object - x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: '`secretRef` required if `disable` + is false.' + rule: '(!has(self.disable) || !self.disable) + ? has(self.secretRef) : true' type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' type: object remote: properties: diff --git a/infra/feast-operator/docs/api/markdown/ref.md b/infra/feast-operator/docs/api/markdown/ref.md index e29ad08e9e..d9702fa6b0 100644 --- a/infra/feast-operator/docs/api/markdown/ref.md +++ b/infra/feast-operator/docs/api/markdown/ref.md @@ -35,9 +35,6 @@ _Appears in:_ ContainerConfigs k8s container settings for the server _Appears in:_ -- [LocalRegistryConfig](#localregistryconfig) -- [OfflineStore](#offlinestore) -- [OnlineStore](#onlinestore) - [ServerConfigs](#serverconfigs) | Field | Description | @@ -57,9 +54,6 @@ DefaultCtrConfigs k8s container settings that are applied by default _Appears in:_ - [ContainerConfigs](#containerconfigs) -- [LocalRegistryConfig](#localregistryconfig) -- [OfflineStore](#offlinestore) -- [OnlineStore](#onlinestore) - [ServerConfigs](#serverconfigs) | Field | Description | @@ -113,7 +107,7 @@ _Appears in:_ | `offlineStore` _[OfflineStore](#offlinestore)_ | | | `onlineStore` _[OnlineStore](#onlinestore)_ | | | `registry` _[Registry](#registry)_ | | -| `ui` _[ServerConfigs](#serverconfigs)_ | | +| `ui` _[ServerConfigs](#serverconfigs)_ | Creates a UI server container | | `deploymentStrategy` _[DeploymentStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#deploymentstrategy-v1-apps)_ | | | `disableInitContainers` _boolean_ | Disable the 'feast repo initialization' initContainer | @@ -185,14 +179,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `image` _string_ | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envvar-v1-core)_ | | -| `envFrom` _[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envfromsource-v1-core)_ | | -| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#pullpolicy-v1-core)_ | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | -| `tls` _[TlsConfigs](#tlsconfigs)_ | | -| `logLevel` _string_ | LogLevel sets the logging level for the server -Allowed values: "debug", "info", "warning", "error", "critical". | +| `server` _[ServerConfigs](#serverconfigs)_ | Creates a registry server container | | `persistence` _[RegistryPersistence](#registrypersistence)_ | | @@ -207,14 +194,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `image` _string_ | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envvar-v1-core)_ | | -| `envFrom` _[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envfromsource-v1-core)_ | | -| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#pullpolicy-v1-core)_ | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | -| `tls` _[TlsConfigs](#tlsconfigs)_ | | -| `logLevel` _string_ | LogLevel sets the logging level for the server -Allowed values: "debug", "info", "warning", "error", "critical". | +| `server` _[ServerConfigs](#serverconfigs)_ | Creates a remote offline server container | | `persistence` _[OfflineStorePersistence](#offlinestorepersistence)_ | | @@ -290,14 +270,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `image` _string_ | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envvar-v1-core)_ | | -| `envFrom` _[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envfromsource-v1-core)_ | | -| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#pullpolicy-v1-core)_ | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | -| `tls` _[TlsConfigs](#tlsconfigs)_ | | -| `logLevel` _string_ | LogLevel sets the logging level for the server -Allowed values: "debug", "info", "warning", "error", "critical". | +| `server` _[ServerConfigs](#serverconfigs)_ | Creates a feature server container | | `persistence` _[OnlineStorePersistence](#onlinestorepersistence)_ | | @@ -355,9 +328,6 @@ OptionalCtrConfigs k8s container settings that are optional _Appears in:_ - [ContainerConfigs](#containerconfigs) -- [LocalRegistryConfig](#localregistryconfig) -- [OfflineStore](#offlinestore) -- [OnlineStore](#onlinestore) - [ServerConfigs](#serverconfigs) | Field | Description | @@ -471,7 +441,7 @@ _Appears in:_ -ServerConfigs server-related configurations for a feast service +ServerConfigs creates a server for the feast service, with specified container configurations. _Appears in:_ - [FeatureStoreServices](#featurestoreservices) @@ -515,9 +485,6 @@ _Appears in:_ TlsConfigs configures server TLS for a feast service. in an openshift cluster, this is configured by default using service serving certificates. _Appears in:_ -- [LocalRegistryConfig](#localregistryconfig) -- [OfflineStore](#offlinestore) -- [OnlineStore](#onlinestore) - [ServerConfigs](#serverconfigs) | Field | Description | diff --git a/infra/feast-operator/internal/controller/featurestore_controller_db_store_test.go b/infra/feast-operator/internal/controller/featurestore_controller_db_store_test.go index a379c33ff1..e4f5847583 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_db_store_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_db_store_test.go @@ -369,17 +369,17 @@ var _ = Describe("FeatureStore Controller - db storage services", func() { Expect(resource.Status.Applied.Services.OfflineStore.Persistence.DBPersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.DBPersistence.Type).To(Equal(string(offlineType))) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.DBPersistence.SecretRef).To(Equal(corev1.LocalObjectReference{Name: "offline-store-secret"})) - Expect(resource.Status.Applied.Services.OfflineStore.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.OfflineStore.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.Applied.Services.OnlineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.DBPersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.DBPersistence.Type).To(Equal(string(onlineType))) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.DBPersistence.SecretRef).To(Equal(corev1.LocalObjectReference{Name: "online-store-secret"})) - Expect(resource.Status.Applied.Services.OnlineStore.ImagePullPolicy).To(Equal(&pullPolicy)) - Expect(resource.Status.Applied.Services.OnlineStore.Resources).NotTo(BeNil()) - Expect(resource.Status.Applied.Services.OnlineStore.Image).To(Equal(&image)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.ImagePullPolicy).To(Equal(&pullPolicy)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Resources).NotTo(BeNil()) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Image).To(Equal(&image)) Expect(resource.Status.Applied.Services.Registry).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence).NotTo(BeNil()) @@ -387,9 +387,9 @@ var _ = Describe("FeatureStore Controller - db storage services", func() { Expect(resource.Status.Applied.Services.Registry.Local.Persistence.DBPersistence.Type).To(Equal(string(registryType))) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.DBPersistence.SecretRef).To(Equal(corev1.LocalObjectReference{Name: "registry-store-secret"})) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.DBPersistence.SecretKeyName).To(Equal("sql_custom_registry_key")) - Expect(resource.Status.Applied.Services.Registry.Local.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.Registry.Local.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.ServiceHostnames.OfflineStore).To(Equal(feast.GetFeastServiceName(services.OfflineFeastType) + "." + resource.Namespace + domain)) Expect(resource.Status.ServiceHostnames.OnlineStore).To(Equal(feast.GetFeastServiceName(services.OnlineFeastType) + "." + resource.Namespace + domain)) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go b/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go index 06d0cd3466..6de38263e7 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go @@ -136,26 +136,26 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(resource.Status.Applied.Services.OfflineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence.Type).To(Equal(offlineType)) - Expect(resource.Status.Applied.Services.OfflineStore.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.OfflineStore.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.Applied.Services.OnlineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence.Path).To(Equal(onlineStorePath)) - Expect(resource.Status.Applied.Services.OnlineStore.Env).To(Equal(&[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}})) - Expect(resource.Status.Applied.Services.OnlineStore.EnvFrom).To(Equal(withEnvFrom())) - Expect(resource.Status.Applied.Services.OnlineStore.ImagePullPolicy).To(Equal(&pullPolicy)) - Expect(resource.Status.Applied.Services.OnlineStore.Resources).NotTo(BeNil()) - Expect(resource.Status.Applied.Services.OnlineStore.Image).To(Equal(&image)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Env).To(Equal(&[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}})) + Expect(resource.Status.Applied.Services.OnlineStore.Server.EnvFrom).To(Equal(withEnvFrom())) + Expect(resource.Status.Applied.Services.OnlineStore.Server.ImagePullPolicy).To(Equal(&pullPolicy)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Resources).NotTo(BeNil()) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Image).To(Equal(&image)) Expect(resource.Status.Applied.Services.Registry).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.Path).To(Equal(registryPath)) - Expect(resource.Status.Applied.Services.Registry.Local.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.Registry.Local.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.ServiceHostnames.OfflineStore).To(Equal(feast.GetFeastServiceName(services.OfflineFeastType) + "." + resource.Namespace + domain)) Expect(resource.Status.ServiceHostnames.OnlineStore).To(Equal(feast.GetFeastServiceName(services.OnlineFeastType) + "." + resource.Namespace + domain)) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_kubernetes_auth_test.go b/infra/feast-operator/internal/controller/featurestore_controller_kubernetes_auth_test.go index 9003fb83d5..dd799a8c8e 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_kubernetes_auth_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_kubernetes_auth_test.go @@ -122,26 +122,26 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { Expect(resource.Status.Applied.Services.OfflineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence.Type).To(Equal(string(services.OfflineFilePersistenceDaskConfigType))) - Expect(resource.Status.Applied.Services.OfflineStore.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.OfflineStore.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.Applied.Services.OnlineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence.Path).To(Equal(services.EphemeralPath + "/" + services.DefaultOnlineStorePath)) - Expect(resource.Status.Applied.Services.OnlineStore.Env).To(Equal(&[]corev1.EnvVar{})) - Expect(resource.Status.Applied.Services.OnlineStore.EnvFrom).To(Equal(withEnvFrom())) - Expect(resource.Status.Applied.Services.OnlineStore.ImagePullPolicy).To(Equal(&pullPolicy)) - Expect(resource.Status.Applied.Services.OnlineStore.Resources).NotTo(BeNil()) - Expect(resource.Status.Applied.Services.OnlineStore.Image).To(Equal(&image)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Env).To(Equal(&[]corev1.EnvVar{})) + Expect(resource.Status.Applied.Services.OnlineStore.Server.EnvFrom).To(Equal(withEnvFrom())) + Expect(resource.Status.Applied.Services.OnlineStore.Server.ImagePullPolicy).To(Equal(&pullPolicy)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Resources).NotTo(BeNil()) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Image).To(Equal(&image)) Expect(resource.Status.Applied.Services.Registry).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.Path).To(Equal(services.EphemeralPath + "/" + services.DefaultRegistryPath)) - Expect(resource.Status.Applied.Services.Registry.Local.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.Registry.Local.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.ServiceHostnames.OfflineStore).To(Equal(feast.GetFeastServiceName(services.OfflineFeastType) + "." + resource.Namespace + domain)) Expect(resource.Status.ServiceHostnames.OnlineStore).To(Equal(feast.GetFeastServiceName(services.OnlineFeastType) + "." + resource.Namespace + domain)) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_loglevel_test.go b/infra/feast-operator/internal/controller/featurestore_controller_loglevel_test.go index bdd1d86731..418e57bb8e 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_loglevel_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_loglevel_test.go @@ -61,23 +61,23 @@ var _ = Describe("FeatureStore Controller - Feast service LogLevel", func() { Services: &feastdevv1alpha1.FeatureStoreServices{ Registry: &feastdevv1alpha1.Registry{ Local: &feastdevv1alpha1.LocalRegistryConfig{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ - LogLevel: "error", + Server: &feastdevv1alpha1.ServerConfigs{ + LogLevel: strPtr("error"), }, }, }, OnlineStore: &feastdevv1alpha1.OnlineStore{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ - LogLevel: "debug", + Server: &feastdevv1alpha1.ServerConfigs{ + LogLevel: strPtr("debug"), }, }, OfflineStore: &feastdevv1alpha1.OfflineStore{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ - LogLevel: "info", + Server: &feastdevv1alpha1.ServerConfigs{ + LogLevel: strPtr("info"), }, }, UI: &feastdevv1alpha1.ServerConfigs{ - LogLevel: "info", + LogLevel: strPtr("info"), }, }, }, @@ -194,10 +194,9 @@ var _ = Describe("FeatureStore Controller - Feast service LogLevel", func() { Expect(err).NotTo(HaveOccurred()) resource.Spec.Services = &feastdevv1alpha1.FeatureStoreServices{ - Registry: &feastdevv1alpha1.Registry{ - Local: &feastdevv1alpha1.LocalRegistryConfig{}, + OnlineStore: &feastdevv1alpha1.OnlineStore{ + Server: &feastdevv1alpha1.ServerConfigs{}, }, - OnlineStore: &feastdevv1alpha1.OnlineStore{}, OfflineStore: &feastdevv1alpha1.OfflineStore{}, UI: &feastdevv1alpha1.ServerConfigs{}, } @@ -230,13 +229,10 @@ var _ = Describe("FeatureStore Controller - Feast service LogLevel", func() { Namespace: objMeta.Namespace, }, deploy) Expect(err).NotTo(HaveOccurred()) - Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(4)) + Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(3)) command := services.GetRegistryContainer(*deploy).Command Expect(command).NotTo(ContainElement("--log-level")) - command = services.GetOfflineContainer(*deploy).Command - Expect(command).NotTo(ContainElement("--log-level")) - command = services.GetOnlineContainer(*deploy).Command Expect(command).NotTo(ContainElement("--log-level")) @@ -246,3 +242,7 @@ var _ = Describe("FeatureStore Controller - Feast service LogLevel", func() { }) }) + +func strPtr(str string) *string { + return &str +} diff --git a/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go b/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go index 12ab5cc4d9..aed8db000e 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go @@ -137,9 +137,9 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.S3AdditionalKwargs).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.S3AdditionalKwargs).To(Equal(&s3AdditionalKwargs)) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.PvcConfig).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.Registry.Local.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.ServiceHostnames.OfflineStore).To(BeEmpty()) Expect(resource.Status.ServiceHostnames.OnlineStore).To(BeEmpty()) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_oidc_auth_test.go b/infra/feast-operator/internal/controller/featurestore_controller_oidc_auth_test.go index 590f7335d2..f192d07cd0 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_oidc_auth_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_oidc_auth_test.go @@ -145,26 +145,26 @@ var _ = Describe("FeatureStore Controller-OIDC authorization", func() { Expect(resource.Status.Applied.Services.OfflineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence.Type).To(Equal(string(services.OfflineFilePersistenceDaskConfigType))) - Expect(resource.Status.Applied.Services.OfflineStore.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.OfflineStore.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.Applied.Services.OnlineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence.Path).To(Equal(services.EphemeralPath + "/" + services.DefaultOnlineStorePath)) - Expect(resource.Status.Applied.Services.OnlineStore.Env).To(Equal(&[]corev1.EnvVar{})) - Expect(resource.Status.Applied.Services.OnlineStore.EnvFrom).To(Equal(withEnvFrom())) - Expect(resource.Status.Applied.Services.OnlineStore.ImagePullPolicy).To(Equal(&pullPolicy)) - Expect(resource.Status.Applied.Services.OnlineStore.Resources).NotTo(BeNil()) - Expect(resource.Status.Applied.Services.OnlineStore.Image).To(Equal(&image)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Env).To(Equal(&[]corev1.EnvVar{})) + Expect(resource.Status.Applied.Services.OnlineStore.Server.EnvFrom).To(Equal(withEnvFrom())) + Expect(resource.Status.Applied.Services.OnlineStore.Server.ImagePullPolicy).To(Equal(&pullPolicy)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Resources).NotTo(BeNil()) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Image).To(Equal(&image)) Expect(resource.Status.Applied.Services.Registry).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.Path).To(Equal(services.EphemeralPath + "/" + services.DefaultRegistryPath)) - Expect(resource.Status.Applied.Services.Registry.Local.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.Registry.Local.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.ServiceHostnames.OfflineStore).To(Equal(feast.GetFeastServiceName(services.OfflineFeastType) + "." + resource.Namespace + domain)) Expect(resource.Status.ServiceHostnames.OnlineStore).To(Equal(feast.GetFeastServiceName(services.OnlineFeastType) + "." + resource.Namespace + domain)) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go b/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go index 488b066166..bb795e8972 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go @@ -177,9 +177,9 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { } Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence.PvcConfig.Create.Resources).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence.PvcConfig.Create.Resources).To(Equal(expectedResources)) - Expect(resource.Status.Applied.Services.OfflineStore.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.OfflineStore.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.Applied.Services.OnlineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence).NotTo(BeNil()) @@ -195,11 +195,11 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { } Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence.PvcConfig.Create.Resources).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence.PvcConfig.Create.Resources).To(Equal(expectedResources)) - Expect(resource.Status.Applied.Services.OnlineStore.Env).To(Equal(&[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}})) - Expect(resource.Status.Applied.Services.OnlineStore.EnvFrom).To(Equal(withEnvFrom())) - Expect(resource.Status.Applied.Services.OnlineStore.ImagePullPolicy).To(Equal(&pullPolicy)) - Expect(resource.Status.Applied.Services.OnlineStore.Resources).NotTo(BeNil()) - Expect(resource.Status.Applied.Services.OnlineStore.Image).To(Equal(&image)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Env).To(Equal(&[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}})) + Expect(resource.Status.Applied.Services.OnlineStore.Server.EnvFrom).To(Equal(withEnvFrom())) + Expect(resource.Status.Applied.Services.OnlineStore.Server.ImagePullPolicy).To(Equal(&pullPolicy)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Resources).NotTo(BeNil()) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Image).To(Equal(&image)) Expect(resource.Status.Applied.Services.Registry).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence).NotTo(BeNil()) @@ -216,9 +216,9 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { } Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.PvcConfig.Create.Resources).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.PvcConfig.Create.Resources).To(Equal(expectedResources)) - Expect(resource.Status.Applied.Services.Registry.Local.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.Registry.Local.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.ServiceHostnames.OfflineStore).To(Equal(feast.GetFeastServiceName(services.OfflineFeastType) + "." + resource.Namespace + domain)) Expect(resource.Status.ServiceHostnames.OnlineStore).To(Equal(feast.GetFeastServiceName(services.OnlineFeastType) + "." + resource.Namespace + domain)) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_test.go b/infra/feast-operator/internal/controller/featurestore_controller_test.go index c3512dd783..f1259162c0 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_test.go @@ -168,9 +168,9 @@ var _ = Describe("FeatureStore Controller", func() { Expect(resource.Status.Applied.Services.Registry).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore).To(BeNil()) Expect(resource.Status.Applied.Services.Registry.Remote).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.Registry.Local.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) @@ -492,26 +492,26 @@ var _ = Describe("FeatureStore Controller", func() { Expect(resource.Status.Applied.Services.OfflineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore.Persistence.FilePersistence.Type).To(Equal("dask")) - Expect(resource.Status.Applied.Services.OfflineStore.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.OfflineStore.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.OfflineStore.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.OfflineStore.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.Applied.Services.OnlineStore).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OnlineStore.Persistence.FilePersistence.Path).To(Equal(services.EphemeralPath + "/" + services.DefaultOnlineStorePath)) - Expect(resource.Status.Applied.Services.OnlineStore.Env).To(Equal(&[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}})) - Expect(resource.Status.Applied.Services.OnlineStore.EnvFrom).To(Equal(withEnvFrom())) - Expect(resource.Status.Applied.Services.OnlineStore.ImagePullPolicy).To(Equal(&pullPolicy)) - Expect(resource.Status.Applied.Services.OnlineStore.Resources).NotTo(BeNil()) - Expect(resource.Status.Applied.Services.OnlineStore.Image).To(Equal(&image)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Env).To(Equal(&[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}})) + Expect(resource.Status.Applied.Services.OnlineStore.Server.EnvFrom).To(Equal(withEnvFrom())) + Expect(resource.Status.Applied.Services.OnlineStore.Server.ImagePullPolicy).To(Equal(&pullPolicy)) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Resources).NotTo(BeNil()) + Expect(resource.Status.Applied.Services.OnlineStore.Server.Image).To(Equal(&image)) Expect(resource.Status.Applied.Services.Registry).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence).NotTo(BeNil()) Expect(resource.Status.Applied.Services.Registry.Local.Persistence.FilePersistence.Path).To(Equal(services.EphemeralPath + "/" + services.DefaultRegistryPath)) - Expect(resource.Status.Applied.Services.Registry.Local.ImagePullPolicy).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Resources).To(BeNil()) - Expect(resource.Status.Applied.Services.Registry.Local.Image).To(Equal(&services.DefaultImage)) + Expect(resource.Status.Applied.Services.Registry.Local.Server.ImagePullPolicy).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Resources).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry.Local.Server.Image).To(Equal(&services.DefaultImage)) Expect(resource.Status.Applied.Services.UI).NotTo(BeNil()) Expect(resource.Status.Applied.Services.UI.Env).To(Equal(&[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}})) Expect(resource.Status.Applied.Services.UI.EnvFrom).To(Equal(withEnvFrom())) @@ -848,7 +848,7 @@ var _ = Describe("FeatureStore Controller", func() { // change feast project and reconcile resourceNew := resource.DeepCopy() - resourceNew.Spec.Services.OnlineStore.Env = &[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue + "1"}, {Name: services.TmpFeatureStoreYamlEnvVar, Value: fsYamlStr}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}}}} + resourceNew.Spec.Services.OnlineStore.Server.Env = &[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue + "1"}, {Name: services.TmpFeatureStoreYamlEnvVar, Value: fsYamlStr}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}}}} err = k8sClient.Update(ctx, resourceNew) Expect(err).NotTo(HaveOccurred()) _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{ @@ -858,7 +858,7 @@ var _ = Describe("FeatureStore Controller", func() { err = k8sClient.Get(ctx, typeNamespacedName, resource) Expect(err).NotTo(HaveOccurred()) - Expect(areEnvVarArraysEqual(*resource.Status.Applied.Services.OnlineStore.Env, []corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue + "1"}, {Name: services.TmpFeatureStoreYamlEnvVar, Value: fsYamlStr}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}}}})).To(BeTrue()) + Expect(areEnvVarArraysEqual(*resource.Status.Applied.Services.OnlineStore.Server.Env, []corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue + "1"}, {Name: services.TmpFeatureStoreYamlEnvVar, Value: fsYamlStr}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}}}})).To(BeTrue()) err = k8sClient.Get(ctx, types.NamespacedName{ Name: objMeta.Name, Namespace: objMeta.Namespace, @@ -965,7 +965,9 @@ var _ = Describe("FeatureStore Controller", func() { Spec: feastdevv1alpha1.FeatureStoreSpec{ FeastProject: referencedRegistry.Spec.FeastProject, Services: &feastdevv1alpha1.FeatureStoreServices{ - OnlineStore: &feastdevv1alpha1.OnlineStore{}, + OnlineStore: &feastdevv1alpha1.OnlineStore{ + Server: &feastdevv1alpha1.ServerConfigs{}, + }, OfflineStore: &feastdevv1alpha1.OfflineStore{}, Registry: &feastdevv1alpha1.Registry{ Remote: &feastdevv1alpha1.RemoteRegistryConfig{ @@ -1037,6 +1039,15 @@ var _ = Describe("FeatureStore Controller", func() { }, } + req, err := labels.NewRequirement(services.NameLabelKey, selection.Equals, []string{resource.Name}) + Expect(err).NotTo(HaveOccurred()) + labelSelector := labels.NewSelector().Add(*req) + listOpts := &client.ListOptions{Namespace: resource.Namespace, LabelSelector: labelSelector} + svcList := corev1.ServiceList{} + err = k8sClient.List(ctx, &svcList, listOpts) + Expect(err).NotTo(HaveOccurred()) + Expect(svcList.Items).To(HaveLen(1)) + // check deployment deploy := &appsv1.Deployment{} objMeta := feast.GetObjectMeta() @@ -1061,11 +1072,6 @@ var _ = Describe("FeatureStore Controller", func() { Project: feastProject, Provider: services.LocalProviderType, EntityKeySerializationVersion: feastdevv1alpha1.SerializationVersion, - OfflineStore: services.OfflineStoreConfig{ - Host: "feast-" + resource.Name + "-offline.default.svc.cluster.local", - Type: services.OfflineRemoteConfigType, - Port: services.HttpPort, - }, OnlineStore: services.OnlineStoreConfig{ Path: "http://feast-" + resource.Name + "-online.default.svc.cluster.local:80", Type: services.OnlineRemoteConfigType, diff --git a/infra/feast-operator/internal/controller/featurestore_controller_test_utils_test.go b/infra/feast-operator/internal/controller/featurestore_controller_test_utils_test.go index e49ba3a920..c1d0cd0f0e 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_test_utils_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_test_utils_test.go @@ -105,7 +105,7 @@ func createFeatureStoreResource(resourceName string, image string, pullPolicy co FeastProject: feastProject, Services: &feastdevv1alpha1.FeatureStoreServices{ OfflineStore: &feastdevv1alpha1.OfflineStore{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ ContainerConfigs: feastdevv1alpha1.ContainerConfigs{ OptionalCtrConfigs: feastdevv1alpha1.OptionalCtrConfigs{ EnvFrom: envFromVar, @@ -114,7 +114,7 @@ func createFeatureStoreResource(resourceName string, image string, pullPolicy co }, }, OnlineStore: &feastdevv1alpha1.OnlineStore{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ ContainerConfigs: feastdevv1alpha1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1alpha1.DefaultCtrConfigs{ Image: &image, diff --git a/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go b/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go index 60d6b2224f..883cfe940a 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go @@ -71,18 +71,18 @@ var _ = Describe("FeatureStore Controller - Feast service TLS", func() { FeastProject: feastProject, Services: &feastdevv1alpha1.FeatureStoreServices{ OnlineStore: &feastdevv1alpha1.OnlineStore{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ TLS: tlsConfigs, }, }, OfflineStore: &feastdevv1alpha1.OfflineStore{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ TLS: tlsConfigs, }, }, Registry: &feastdevv1alpha1.Registry{ Local: &feastdevv1alpha1.LocalRegistryConfig{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ TLS: tlsConfigs, }, }, @@ -356,14 +356,14 @@ var _ = Describe("FeatureStore Controller - Feast service TLS", func() { FeastProject: feastProject, Services: &feastdevv1alpha1.FeatureStoreServices{ OnlineStore: &feastdevv1alpha1.OnlineStore{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ TLS: &feastdevv1alpha1.TlsConfigs{ Disable: &disable, }, }, }, OfflineStore: &feastdevv1alpha1.OfflineStore{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ TLS: tlsConfigs, }, }, diff --git a/infra/feast-operator/internal/controller/services/repo_config.go b/infra/feast-operator/internal/controller/services/repo_config.go index 0a5dd11544..50ad3b9285 100644 --- a/infra/feast-operator/internal/controller/services/repo_config.go +++ b/infra/feast-operator/internal/controller/services/repo_config.go @@ -239,8 +239,9 @@ func getClientRepoConfig( Host: strings.Split(status.ServiceHostnames.OfflineStore, ":")[0], Port: HttpPort, } - if appliedServices.OfflineStore != nil && appliedServices.OfflineStore.TLS.IsTLS() { - clientRepoConfig.OfflineStore.Cert = GetTlsPath(OfflineFeastType) + appliedServices.OfflineStore.TLS.SecretKeyNames.TlsCrt + if appliedServices.OfflineStore != nil && + appliedServices.OfflineStore.Server != nil && appliedServices.OfflineStore.Server.TLS.IsTLS() { + clientRepoConfig.OfflineStore.Cert = GetTlsPath(OfflineFeastType) + appliedServices.OfflineStore.Server.TLS.SecretKeyNames.TlsCrt clientRepoConfig.OfflineStore.Port = HttpsPort clientRepoConfig.OfflineStore.Scheme = HttpsScheme } @@ -251,8 +252,9 @@ func getClientRepoConfig( Type: OnlineRemoteConfigType, Path: HttpScheme + onlinePath, } - if appliedServices.OnlineStore != nil && appliedServices.OnlineStore.TLS.IsTLS() { - clientRepoConfig.OnlineStore.Cert = GetTlsPath(OnlineFeastType) + appliedServices.OnlineStore.TLS.SecretKeyNames.TlsCrt + if appliedServices.OnlineStore != nil && + appliedServices.OnlineStore.Server != nil && appliedServices.OnlineStore.Server.TLS.IsTLS() { + clientRepoConfig.OnlineStore.Cert = GetTlsPath(OnlineFeastType) + appliedServices.OnlineStore.Server.TLS.SecretKeyNames.TlsCrt clientRepoConfig.OnlineStore.Path = HttpsScheme + onlinePath } } @@ -262,7 +264,7 @@ func getClientRepoConfig( Path: status.ServiceHostnames.Registry, } if localRegistryTls(featureStore) { - clientRepoConfig.Registry.Cert = GetTlsPath(RegistryFeastType) + appliedServices.Registry.Local.TLS.SecretKeyNames.TlsCrt + clientRepoConfig.Registry.Cert = GetTlsPath(RegistryFeastType) + appliedServices.Registry.Local.Server.TLS.SecretKeyNames.TlsCrt } else if remoteRegistryTls(featureStore) { clientRepoConfig.Registry.Cert = GetTlsPath(RegistryFeastType) + appliedServices.Registry.Remote.TLS.CertName } diff --git a/infra/feast-operator/internal/controller/services/repo_config_test.go b/infra/feast-operator/internal/controller/services/repo_config_test.go index 0ed0fb62e0..8a4c2a6123 100644 --- a/infra/feast-operator/internal/controller/services/repo_config_test.go +++ b/infra/feast-operator/internal/controller/services/repo_config_test.go @@ -365,13 +365,16 @@ func minimalFeatureStore() *feastdevv1alpha1.FeatureStore { } } -func minimalFeatureStoreWithAllServices() *feastdevv1alpha1.FeatureStore { +func minimalFeatureStoreWithAllServers() *feastdevv1alpha1.FeatureStore { feast := minimalFeatureStore() feast.Spec.Services = &feastdevv1alpha1.FeatureStoreServices{ - OfflineStore: &feastdevv1alpha1.OfflineStore{}, - OnlineStore: &feastdevv1alpha1.OnlineStore{}, - Registry: &feastdevv1alpha1.Registry{}, - UI: &feastdevv1alpha1.ServerConfigs{}, + OfflineStore: &feastdevv1alpha1.OfflineStore{ + Server: &feastdevv1alpha1.ServerConfigs{}, + }, + OnlineStore: &feastdevv1alpha1.OnlineStore{ + Server: &feastdevv1alpha1.ServerConfigs{}, + }, + UI: &feastdevv1alpha1.ServerConfigs{}, } return feast } diff --git a/infra/feast-operator/internal/controller/services/services.go b/infra/feast-operator/internal/controller/services/services.go index cc7d1d215f..a1151487b6 100644 --- a/infra/feast-operator/internal/controller/services/services.go +++ b/infra/feast-operator/internal/controller/services/services.go @@ -51,8 +51,8 @@ func (feast *FeastServices) ApplyDefaults() error { // Deploy the feast services func (feast *FeastServices) Deploy() error { - if feast.noLocalServiceConfigured() { - return errors.New("at least one local service must be configured. e.g. registry / online / offline") + if feast.noLocalCoreServerConfigured() { + return errors.New("at least one local server must be configured. e.g. registry / online / offline") } openshiftTls, err := feast.checkOpenshiftTls() if err != nil { @@ -67,7 +67,7 @@ func (feast *FeastServices) Deploy() error { } services := feast.Handler.FeatureStore.Status.Applied.Services - if feast.isOfflinStore() { + if feast.isOfflineStore() { err := feast.validateOfflineStorePersistence(services.OfflineStore.Persistence) if err != nil { return err @@ -82,7 +82,7 @@ func (feast *FeastServices) Deploy() error { } } - if feast.isOnlinStore() { + if feast.isOnlineStore() { err := feast.validateOnlineStorePersistence(services.OnlineStore.Persistence) if err != nil { return err @@ -111,7 +111,7 @@ func (feast *FeastServices) Deploy() error { return err } } - if feast.isUI() { + if feast.isUiServer() { if err = feast.deployFeastServiceByType(UIFeastType); err != nil { return err } @@ -125,7 +125,6 @@ func (feast *FeastServices) Deploy() error { if err := feast.removeRoute(UIFeastType); err != nil { return err } - } if err := feast.createServiceAccount(); err != nil { @@ -218,8 +217,12 @@ func (feast *FeastServices) deployFeastServiceByType(feastType FeastServiceType) } else { _ = feast.Handler.DeleteOwnedFeastObj(feast.initPVC(feastType)) } - if err := feast.createService(feastType); err != nil { - return feast.setFeastServiceCondition(err, feastType) + if serviceConfig := feast.getServerConfigs(feastType); serviceConfig != nil { + if err := feast.createService(feastType); err != nil { + return feast.setFeastServiceCondition(err, feastType) + } + } else { + _ = feast.Handler.DeleteOwnedFeastObj(feast.initFeastSvc(feastType)) } return feast.setFeastServiceCondition(nil, feastType) } @@ -363,62 +366,62 @@ func (feast *FeastServices) setContainers(podSpec *corev1.PodSpec) error { } feast.setInitContainer(podSpec, fsYamlB64) - - if feast.isLocalRegistry() { + if feast.isRegistryServer() { feast.setContainer(&podSpec.Containers, RegistryFeastType, fsYamlB64) } - if feast.isOfflinStore() { - feast.setContainer(&podSpec.Containers, OfflineFeastType, fsYamlB64) - } - if feast.isOnlinStore() { + if feast.isOnlineServer() { feast.setContainer(&podSpec.Containers, OnlineFeastType, fsYamlB64) } - if feast.isUI() { + if feast.isOfflineServer() { + feast.setContainer(&podSpec.Containers, OfflineFeastType, fsYamlB64) + } + if feast.isUiServer() { feast.setContainer(&podSpec.Containers, UIFeastType, fsYamlB64) } return nil } func (feast *FeastServices) setContainer(containers *[]corev1.Container, feastType FeastServiceType, fsYamlB64 string) { - tls := feast.getTlsConfigs(feastType) - containerConfigs := feast.getContainerConfigs(feastType) - defaultCtrConfigs := containerConfigs.DefaultCtrConfigs - probeHandler := getProbeHandler(feastType, tls) - container := &corev1.Container{ - Name: string(feastType), - Image: *defaultCtrConfigs.Image, - WorkingDir: getOfflineMountPath(feast.Handler.FeatureStore) + "/" + feast.Handler.FeatureStore.Status.Applied.FeastProject + FeatureRepoDir, - Command: feast.getContainerCommand(feastType), - Ports: []corev1.ContainerPort{ - { - Name: string(feastType), - ContainerPort: getTargetPort(feastType, tls), - Protocol: corev1.ProtocolTCP, + if serverConfigs := feast.getServerConfigs(feastType); serverConfigs != nil { + defaultCtrConfigs := serverConfigs.ContainerConfigs.DefaultCtrConfigs + tls := feast.getTlsConfigs(feastType) + probeHandler := getProbeHandler(feastType, tls) + container := &corev1.Container{ + Name: string(feastType), + Image: *defaultCtrConfigs.Image, + WorkingDir: getOfflineMountPath(feast.Handler.FeatureStore) + "/" + feast.Handler.FeatureStore.Status.Applied.FeastProject + FeatureRepoDir, + Command: feast.getContainerCommand(feastType), + Ports: []corev1.ContainerPort{ + { + Name: string(feastType), + ContainerPort: getTargetPort(feastType, tls), + Protocol: corev1.ProtocolTCP, + }, }, - }, - Env: []corev1.EnvVar{ - { - Name: TmpFeatureStoreYamlEnvVar, - Value: fsYamlB64, + Env: []corev1.EnvVar{ + { + Name: TmpFeatureStoreYamlEnvVar, + Value: fsYamlB64, + }, }, - }, - StartupProbe: &corev1.Probe{ - ProbeHandler: probeHandler, - PeriodSeconds: 3, - FailureThreshold: 40, - }, - LivenessProbe: &corev1.Probe{ - ProbeHandler: probeHandler, - PeriodSeconds: 20, - FailureThreshold: 6, - }, - ReadinessProbe: &corev1.Probe{ - ProbeHandler: probeHandler, - PeriodSeconds: 10, - }, + StartupProbe: &corev1.Probe{ + ProbeHandler: probeHandler, + PeriodSeconds: 3, + FailureThreshold: 40, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: probeHandler, + PeriodSeconds: 20, + FailureThreshold: 6, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: probeHandler, + PeriodSeconds: 10, + }, + } + applyOptionalCtrConfigs(container, serverConfigs.ContainerConfigs.OptionalCtrConfigs) + *containers = append(*containers, *container) } - applyOptionalCtrConfigs(container, containerConfigs.OptionalCtrConfigs) - *containers = append(*containers, *container) } func (feast *FeastServices) setRoute(route *routev1.Route, feastType FeastServiceType) error { @@ -554,48 +557,30 @@ func (feast *FeastServices) createNewPVC(pvcCreate *feastdevv1alpha1.PvcCreate, return pvc, controllerutil.SetControllerReference(feast.Handler.FeatureStore, pvc, feast.Handler.Scheme) } -func (feast *FeastServices) getContainerConfigs(feastType FeastServiceType) feastdevv1alpha1.ContainerConfigs { +func (feast *FeastServices) getServerConfigs(feastType FeastServiceType) *feastdevv1alpha1.ServerConfigs { appliedServices := feast.Handler.FeatureStore.Status.Applied.Services switch feastType { case OfflineFeastType: - if feast.isOfflinStore() { - return appliedServices.OfflineStore.ServerConfigs.ContainerConfigs + if feast.isOfflineStore() { + return appliedServices.OfflineStore.Server } case OnlineFeastType: - if feast.isOnlinStore() { - return appliedServices.OnlineStore.ServerConfigs.ContainerConfigs + if feast.isOnlineStore() { + return appliedServices.OnlineStore.Server } case RegistryFeastType: if feast.isLocalRegistry() { - return appliedServices.Registry.Local.ServerConfigs.ContainerConfigs + return appliedServices.Registry.Local.Server } case UIFeastType: - if feast.isUI() { - return appliedServices.UI.ContainerConfigs - } + return appliedServices.UI } - return feastdevv1alpha1.ContainerConfigs{} + return nil } func (feast *FeastServices) getLogLevelForType(feastType FeastServiceType) *string { - services := feast.Handler.FeatureStore.Status.Applied.Services - switch feastType { - case OfflineFeastType: - if services.OfflineStore != nil && services.OfflineStore.LogLevel != "" { - return &services.OfflineStore.LogLevel - } - case OnlineFeastType: - if services.OnlineStore != nil && services.OnlineStore.LogLevel != "" { - return &services.OnlineStore.LogLevel - } - case RegistryFeastType: - if feast.isLocalRegistry() && services.Registry.Local.LogLevel != "" { - return &services.Registry.Local.LogLevel - } - case UIFeastType: - if services.UI != nil && services.UI.LogLevel != "" { - return &services.UI.LogLevel - } + if serviceConfigs := feast.getServerConfigs(feastType); serviceConfigs != nil { + return serviceConfigs.LogLevel } return nil } @@ -645,24 +630,24 @@ func (feast *FeastServices) getLabels() map[string]string { func (feast *FeastServices) setServiceHostnames() error { feast.Handler.FeatureStore.Status.ServiceHostnames = feastdevv1alpha1.ServiceHostnames{} domain := svcDomain + ":" - if feast.isOfflinStore() { + if feast.isOfflineServer() { objMeta := feast.initFeastSvc(OfflineFeastType) feast.Handler.FeatureStore.Status.ServiceHostnames.OfflineStore = objMeta.Name + "." + objMeta.Namespace + domain + - getPortStr(feast.Handler.FeatureStore.Status.Applied.Services.OfflineStore.TLS) + getPortStr(feast.Handler.FeatureStore.Status.Applied.Services.OfflineStore.Server.TLS) } - if feast.isOnlinStore() { + if feast.isOnlineServer() { objMeta := feast.initFeastSvc(OnlineFeastType) feast.Handler.FeatureStore.Status.ServiceHostnames.OnlineStore = objMeta.Name + "." + objMeta.Namespace + domain + - getPortStr(feast.Handler.FeatureStore.Status.Applied.Services.OnlineStore.TLS) + getPortStr(feast.Handler.FeatureStore.Status.Applied.Services.OnlineStore.Server.TLS) } - if feast.isLocalRegistry() { + if feast.isRegistryServer() { objMeta := feast.initFeastSvc(RegistryFeastType) feast.Handler.FeatureStore.Status.ServiceHostnames.Registry = objMeta.Name + "." + objMeta.Namespace + domain + - getPortStr(feast.Handler.FeatureStore.Status.Applied.Services.Registry.Local.TLS) + getPortStr(feast.Handler.FeatureStore.Status.Applied.Services.Registry.Local.Server.TLS) } else if feast.isRemoteRegistry() { return feast.setRemoteRegistryURL() } - if feast.isUI() { + if feast.isUiServer() { objMeta := feast.initFeastSvc(UIFeastType) feast.Handler.FeatureStore.Status.ServiceHostnames.UI = objMeta.Name + "." + objMeta.Namespace + domain + getPortStr(feast.Handler.FeatureStore.Status.Applied.Services.UI.TLS) @@ -693,10 +678,11 @@ func (feast *FeastServices) setRemoteRegistryURL() error { if err != nil { return err } - // referenced/remote registry must use the local install option and be in a 'Ready' state. + // referenced/remote registry must use the local registry server option and be in a 'Ready' state. if remoteFeast != nil && - remoteFeast.isLocalRegistry() && - apimeta.IsStatusConditionTrue(remoteFeast.Handler.FeatureStore.Status.Conditions, feastdevv1alpha1.RegistryReadyType) { + remoteFeast.isRegistryServer() && + apimeta.IsStatusConditionTrue(remoteFeast.Handler.FeatureStore.Status.Conditions, feastdevv1alpha1.RegistryReadyType) && + len(remoteFeast.Handler.FeatureStore.Status.ServiceHostnames.Registry) > 0 { feast.Handler.FeatureStore.Status.ServiceHostnames.Registry = remoteFeast.Handler.FeatureStore.Status.ServiceHostnames.Registry } else { return errors.New("Remote feast registry of referenced FeatureStore '" + remoteFeast.Handler.FeatureStore.Name + "' is not ready") @@ -739,6 +725,10 @@ func (feast *FeastServices) isLocalRegistry() bool { return IsLocalRegistry(feast.Handler.FeatureStore) } +func (feast *FeastServices) isRegistryServer() bool { + return IsRegistryServer(feast.Handler.FeatureStore) +} + func (feast *FeastServices) isRemoteRegistry() bool { return isRemoteRegistry(feast.Handler.FeatureStore) } @@ -753,21 +743,31 @@ func (feast *FeastServices) isRemoteHostnameRegistry() bool { feast.Handler.FeatureStore.Status.Applied.Services.Registry.Remote.Hostname != nil } -func (feast *FeastServices) isOfflinStore() bool { +func (feast *FeastServices) isOfflineServer() bool { + return feast.isOfflineStore() && + feast.Handler.FeatureStore.Spec.Services.OfflineStore.Server != nil +} + +func (feast *FeastServices) isOfflineStore() bool { appliedServices := feast.Handler.FeatureStore.Status.Applied.Services return appliedServices != nil && appliedServices.OfflineStore != nil } -func (feast *FeastServices) isOnlinStore() bool { +func (feast *FeastServices) isOnlineServer() bool { + return feast.isOnlineStore() && + feast.Handler.FeatureStore.Spec.Services.OnlineStore.Server != nil +} + +func (feast *FeastServices) isOnlineStore() bool { appliedServices := feast.Handler.FeatureStore.Status.Applied.Services return appliedServices != nil && appliedServices.OnlineStore != nil } -func (feast *FeastServices) noLocalServiceConfigured() bool { - return !(feast.isLocalRegistry() || feast.isOnlinStore() || feast.isOfflinStore()) +func (feast *FeastServices) noLocalCoreServerConfigured() bool { + return !(feast.isRegistryServer() || feast.isOnlineServer() || feast.isOfflineServer()) } -func (feast *FeastServices) isUI() bool { +func (feast *FeastServices) isUiServer() bool { appliedServices := feast.Handler.FeatureStore.Status.Applied.Services return appliedServices != nil && appliedServices.UI != nil } diff --git a/infra/feast-operator/internal/controller/services/tls.go b/infra/feast-operator/internal/controller/services/tls.go index 7d8cbd1693..ae3819ab6b 100644 --- a/infra/feast-operator/internal/controller/services/tls.go +++ b/infra/feast-operator/internal/controller/services/tls.go @@ -28,16 +28,16 @@ func (feast *FeastServices) setTlsDefaults() error { return err } appliedServices := feast.Handler.FeatureStore.Status.Applied.Services - if feast.isOfflinStore() && appliedServices.OfflineStore.TLS != nil { - tlsDefaults(appliedServices.OfflineStore.TLS) + if feast.isOfflineServer() { + tlsDefaults(appliedServices.OfflineStore.Server.TLS) } - if feast.isOnlinStore() { - tlsDefaults(appliedServices.OnlineStore.TLS) + if feast.isOnlineServer() { + tlsDefaults(appliedServices.OnlineStore.Server.TLS) } - if feast.isLocalRegistry() { - tlsDefaults(appliedServices.Registry.Local.TLS) + if feast.isRegistryServer() { + tlsDefaults(appliedServices.Registry.Local.Server.TLS) } - if feast.isUI() { + if feast.isUiServer() { tlsDefaults(appliedServices.UI.TLS) } return nil @@ -46,14 +46,14 @@ func (feast *FeastServices) setTlsDefaults() error { func (feast *FeastServices) setOpenshiftTls() error { appliedServices := feast.Handler.FeatureStore.Status.Applied.Services if feast.offlineOpenshiftTls() { - appliedServices.OfflineStore.TLS = &feastdevv1alpha1.TlsConfigs{ + appliedServices.OfflineStore.Server.TLS = &feastdevv1alpha1.TlsConfigs{ SecretRef: &corev1.LocalObjectReference{ Name: feast.initFeastSvc(OfflineFeastType).Name + tlsNameSuffix, }, } } if feast.onlineOpenshiftTls() { - appliedServices.OnlineStore.TLS = &feastdevv1alpha1.TlsConfigs{ + appliedServices.OnlineStore.Server.TLS = &feastdevv1alpha1.TlsConfigs{ SecretRef: &corev1.LocalObjectReference{ Name: feast.initFeastSvc(OnlineFeastType).Name + tlsNameSuffix, }, @@ -66,9 +66,8 @@ func (feast *FeastServices) setOpenshiftTls() error { }, } } - if feast.localRegistryOpenshiftTls() { - appliedServices.Registry.Local.TLS = &feastdevv1alpha1.TlsConfigs{ + appliedServices.Registry.Local.Server.TLS = &feastdevv1alpha1.TlsConfigs{ SecretRef: &corev1.LocalObjectReference{ Name: feast.initFeastSvc(RegistryFeastType).Name + tlsNameSuffix, }, @@ -111,55 +110,40 @@ func (feast *FeastServices) isOpenShiftTls(feastType FeastServiceType) (isOpenSh return } -func (feast *FeastServices) getTlsConfigs(feastType FeastServiceType) (tls *feastdevv1alpha1.TlsConfigs) { - appliedServices := feast.Handler.FeatureStore.Status.Applied.Services - switch feastType { - case OfflineFeastType: - if feast.isOfflinStore() { - tls = appliedServices.OfflineStore.TLS - } - case OnlineFeastType: - if feast.isOnlinStore() { - tls = appliedServices.OnlineStore.TLS - } - case RegistryFeastType: - if feast.isLocalRegistry() { - tls = appliedServices.Registry.Local.TLS - } - case UIFeastType: - if feast.isUI() { - tls = appliedServices.UI.TLS - } +func (feast *FeastServices) getTlsConfigs(feastType FeastServiceType) *feastdevv1alpha1.TlsConfigs { + if serviceConfigs := feast.getServerConfigs(feastType); serviceConfigs != nil { + return serviceConfigs.TLS } - return + return nil } // True if running in an openshift cluster and Tls not configured in the service Spec func (feast *FeastServices) offlineOpenshiftTls() bool { return isOpenShift && - feast.isOfflinStore() && feast.Handler.FeatureStore.Spec.Services.OfflineStore.TLS == nil + feast.isOfflineServer() && feast.Handler.FeatureStore.Spec.Services.OfflineStore.Server.TLS == nil } // True if running in an openshift cluster and Tls not configured in the service Spec func (feast *FeastServices) onlineOpenshiftTls() bool { return isOpenShift && - feast.isOnlinStore() && feast.Handler.FeatureStore.Spec.Services.OnlineStore.TLS == nil + feast.isOnlineServer() && feast.Handler.FeatureStore.Spec.Services.OnlineStore.Server.TLS == nil } // True if running in an openshift cluster and Tls not configured in the service Spec func (feast *FeastServices) uiOpenshiftTls() bool { return isOpenShift && - feast.isUI() && feast.Handler.FeatureStore.Spec.Services.UI.TLS == nil + feast.isUiServer() && feast.Handler.FeatureStore.Spec.Services.UI.TLS == nil } // True if running in an openshift cluster and Tls not configured in the service Spec func (feast *FeastServices) localRegistryOpenshiftTls() bool { return isOpenShift && - feast.isLocalRegistry() && + feast.isRegistryServer() && (feast.Handler.FeatureStore.Spec.Services == nil || feast.Handler.FeatureStore.Spec.Services.Registry == nil || feast.Handler.FeatureStore.Spec.Services.Registry.Local == nil || - feast.Handler.FeatureStore.Spec.Services.Registry.Local.TLS == nil) + feast.Handler.FeatureStore.Spec.Services.Registry.Local.Server == nil || + feast.Handler.FeatureStore.Spec.Services.Registry.Local.Server.TLS == nil) } // True if running in an openshift cluster, and using a remote registry in the same cluster, with no remote Tls set in the service Spec @@ -265,7 +249,7 @@ func tlsDefaults(tls *feastdevv1alpha1.TlsConfigs) { } func localRegistryTls(featureStore *feastdevv1alpha1.FeatureStore) bool { - return IsLocalRegistry(featureStore) && featureStore.Status.Applied.Services.Registry.Local.TLS.IsTLS() + return IsRegistryServer(featureStore) && featureStore.Status.Applied.Services.Registry.Local.Server.TLS.IsTLS() } func remoteRegistryTls(featureStore *feastdevv1alpha1.FeatureStore) bool { diff --git a/infra/feast-operator/internal/controller/services/tls_test.go b/infra/feast-operator/internal/controller/services/tls_test.go index 22102dfb7d..eeae0de3eb 100644 --- a/infra/feast-operator/internal/controller/services/tls_test.go +++ b/infra/feast-operator/internal/controller/services/tls_test.go @@ -43,13 +43,20 @@ var _ = Describe("TLS Config", func() { It("should set default TLS configs", func() { By("Having the created resource") - // registry service w/o tls + // registry server w/o tls feast := FeastServices{ Handler: handler.FeastHandler{ FeatureStore: minimalFeatureStore(), Scheme: scheme, }, } + feast.Handler.FeatureStore.Spec.Services = &feastdevv1alpha1.FeatureStoreServices{ + Registry: &feastdevv1alpha1.Registry{ + Local: &feastdevv1alpha1.LocalRegistryConfig{ + Server: &feastdevv1alpha1.ServerConfigs{}, + }, + }, + } err := feast.ApplyDefaults() Expect(err).ToNot(HaveOccurred()) @@ -72,6 +79,13 @@ var _ = Describe("TLS Config", func() { // registry service w/ openshift tls testSetIsOpenShift() feast.Handler.FeatureStore = minimalFeatureStore() + feast.Handler.FeatureStore.Spec.Services = &feastdevv1alpha1.FeatureStoreServices{ + Registry: &feastdevv1alpha1.Registry{ + Local: &feastdevv1alpha1.LocalRegistryConfig{ + Server: &feastdevv1alpha1.ServerConfigs{}, + }, + }, + } err = feast.ApplyDefaults() Expect(err).ToNot(HaveOccurred()) @@ -103,7 +117,7 @@ var _ = Describe("TLS Config", func() { Expect(openshiftTls).To(BeTrue()) // all services w/ openshift tls - feast.Handler.FeatureStore = minimalFeatureStoreWithAllServices() + feast.Handler.FeatureStore = minimalFeatureStoreWithAllServers() err = feast.ApplyDefaults() Expect(err).ToNot(HaveOccurred()) @@ -164,7 +178,7 @@ var _ = Describe("TLS Config", func() { feast.Handler.FeatureStore = minimalFeatureStore() feast.Handler.FeatureStore.Spec.Services = &feastdevv1alpha1.FeatureStoreServices{ OnlineStore: &feastdevv1alpha1.OnlineStore{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ TLS: &feastdevv1alpha1.TlsConfigs{}, }, }, @@ -173,7 +187,7 @@ var _ = Describe("TLS Config", func() { }, Registry: &feastdevv1alpha1.Registry{ Local: &feastdevv1alpha1.LocalRegistryConfig{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ TLS: &feastdevv1alpha1.TlsConfigs{ SecretRef: &corev1.LocalObjectReference{}, SecretKeyNames: feastdevv1alpha1.SecretKeyNames{ @@ -213,9 +227,9 @@ var _ = Describe("TLS Config", func() { Expect(openshiftTls).To(BeFalse()) // all services w/ tls and in an openshift cluster - feast.Handler.FeatureStore = minimalFeatureStoreWithAllServices() + feast.Handler.FeatureStore = minimalFeatureStoreWithAllServers() disable := true - feast.Handler.FeatureStore.Spec.Services.OnlineStore.TLS = &feastdevv1alpha1.TlsConfigs{ + feast.Handler.FeatureStore.Spec.Services.OnlineStore.Server.TLS = &feastdevv1alpha1.TlsConfigs{ Disable: &disable, } feast.Handler.FeatureStore.Spec.Services.UI.TLS = &feastdevv1alpha1.TlsConfigs{ @@ -223,7 +237,7 @@ var _ = Describe("TLS Config", func() { } feast.Handler.FeatureStore.Spec.Services.Registry = &feastdevv1alpha1.Registry{ Local: &feastdevv1alpha1.LocalRegistryConfig{ - ServerConfigs: feastdevv1alpha1.ServerConfigs{ + Server: &feastdevv1alpha1.ServerConfigs{ TLS: &feastdevv1alpha1.TlsConfigs{ Disable: &disable, }, diff --git a/infra/feast-operator/internal/controller/services/util.go b/infra/feast-operator/internal/controller/services/util.go index fc6f57c780..c4a8f89c67 100644 --- a/infra/feast-operator/internal/controller/services/util.go +++ b/infra/feast-operator/internal/controller/services/util.go @@ -22,6 +22,10 @@ import ( var isOpenShift = false +func IsRegistryServer(featureStore *feastdevv1alpha1.FeatureStore) bool { + return IsLocalRegistry(featureStore) && featureStore.Status.Applied.Services.Registry.Local.Server != nil +} + func IsLocalRegistry(featureStore *feastdevv1alpha1.FeatureStore) bool { appliedServices := featureStore.Status.Applied.Services return appliedServices != nil && appliedServices.Registry != nil && appliedServices.Registry.Local != nil @@ -117,7 +121,10 @@ func ApplyDefaultsToStatus(cr *feastdevv1alpha1.FeatureStore) { ensurePVCDefaults(services.Registry.Local.Persistence.FilePersistence.PvcConfig, RegistryFeastType) } - setDefaultCtrConfigs(&services.Registry.Local.ServerConfigs.ContainerConfigs.DefaultCtrConfigs) + if services.Registry.Local.Server == nil { + services.Registry.Local.Server = &feastdevv1alpha1.ServerConfigs{} + } + setDefaultCtrConfigs(&services.Registry.Local.Server.ContainerConfigs.DefaultCtrConfigs) } else if services.Registry.Remote.FeastRef != nil && len(services.Registry.Remote.FeastRef.Namespace) == 0 { services.Registry.Remote.FeastRef.Namespace = cr.Namespace } @@ -139,7 +146,9 @@ func ApplyDefaultsToStatus(cr *feastdevv1alpha1.FeatureStore) { ensurePVCDefaults(services.OfflineStore.Persistence.FilePersistence.PvcConfig, OfflineFeastType) } - setDefaultCtrConfigs(&services.OfflineStore.ServerConfigs.ContainerConfigs.DefaultCtrConfigs) + if services.OfflineStore.Server != nil { + setDefaultCtrConfigs(&services.OfflineStore.Server.ContainerConfigs.DefaultCtrConfigs) + } } if services.OnlineStore != nil { @@ -159,10 +168,11 @@ func ApplyDefaultsToStatus(cr *feastdevv1alpha1.FeatureStore) { ensurePVCDefaults(services.OnlineStore.Persistence.FilePersistence.PvcConfig, OnlineFeastType) } - setDefaultCtrConfigs(&services.OnlineStore.ServerConfigs.ContainerConfigs.DefaultCtrConfigs) + if services.OnlineStore.Server != nil { + setDefaultCtrConfigs(&services.OnlineStore.Server.ContainerConfigs.DefaultCtrConfigs) + } } if services.UI != nil { - setDefaultCtrConfigs(&services.UI.ContainerConfigs.DefaultCtrConfigs) } } diff --git a/infra/feast-operator/test/testdata/feast_integration_test_crs/v1alpha1_default_featurestore.yaml b/infra/feast-operator/test/testdata/feast_integration_test_crs/v1alpha1_default_featurestore.yaml index 9ce14113de..3d707fbafd 100644 --- a/infra/feast-operator/test/testdata/feast_integration_test_crs/v1alpha1_default_featurestore.yaml +++ b/infra/feast-operator/test/testdata/feast_integration_test_crs/v1alpha1_default_featurestore.yaml @@ -5,6 +5,8 @@ metadata: spec: feastProject: my_project services: - onlineStore: {} - offlineStore: {} + onlineStore: + server: {} + offlineStore: + server: {} ui: {} diff --git a/infra/feast-operator/test/testdata/feast_integration_test_crs/v1alpha1_remote_registry_featurestore.yaml b/infra/feast-operator/test/testdata/feast_integration_test_crs/v1alpha1_remote_registry_featurestore.yaml index a8845d2963..73f8880dc1 100644 --- a/infra/feast-operator/test/testdata/feast_integration_test_crs/v1alpha1_remote_registry_featurestore.yaml +++ b/infra/feast-operator/test/testdata/feast_integration_test_crs/v1alpha1_remote_registry_featurestore.yaml @@ -5,8 +5,10 @@ metadata: spec: feastProject: my_project services: - onlineStore: {} - offlineStore: {} + onlineStore: + server: {} + offlineStore: + server: {} ui: {} registry: remote: