From 3834ffa31f52b9a68b27a9f898538827ee8e5c39 Mon Sep 17 00:00:00 2001 From: lokeshrangineni <19699092+lokeshrangineni@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:47:49 -0500 Subject: [PATCH 01/30] fix: Setting the github_token explicitly to see if that solves the problem. (#5012) setting the github_token explicitly to see if that solves the problem. Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d76be8506f1..09fe7152dcf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -191,6 +191,7 @@ jobs: GIT_AUTHOR_EMAIL: feast-ci-bot@willem.co GIT_COMMITTER_NAME: feast-ci-bot GIT_COMMITTER_EMAIL: feast-ci-bot@willem.co + GITHUB_REPOSITORY: ${{ github.repository }} steps: - name: Checkout code uses: actions/checkout@v4 @@ -201,6 +202,7 @@ jobs: run: | git config --global user.name "$GIT_AUTHOR_NAME" git config --global user.email "$GIT_AUTHOR_EMAIL" + git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY} - name: Fetch all branches run: git fetch --all From b9325b7f42b8866fa43b1c7567e3288dd589020f Mon Sep 17 00:00:00 2001 From: lokeshrangineni <19699092+lokeshrangineni@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:22:34 -0500 Subject: [PATCH 02/30] feat: Moving the job to seperate action so that we can test it easily. (#5013) * setting the github_token explicitly to see if that solves the problem. Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> * Moving the job to seperate action so that we can test it easily. Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> --------- Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> --- .github/workflows/update_stable_branch.yml | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/update_stable_branch.yml diff --git a/.github/workflows/update_stable_branch.yml b/.github/workflows/update_stable_branch.yml new file mode 100644 index 00000000000..b09af9cc2eb --- /dev/null +++ b/.github/workflows/update_stable_branch.yml @@ -0,0 +1,40 @@ +name: Update Stable Branch + +on: + workflow_dispatch: + inputs: + token: + description: 'GitHub token to authenticate' + required: true + type: string + +jobs: + update_stable_branch: + name: Update Stable Branch after release + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ github.event.inputs.token }} + GIT_AUTHOR_NAME: feast-ci-bot + GIT_AUTHOR_EMAIL: feast-ci-bot@willem.co + GIT_COMMITTER_NAME: feast-ci-bot + GIT_COMMITTER_EMAIL: feast-ci-bot@willem.co + GITHUB_REPOSITORY: ${{ github.repository }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Git credentials + run: | + git config --global user.name "$GIT_AUTHOR_NAME" + git config --global user.email "$GIT_AUTHOR_EMAIL" + git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY} + + - name: Fetch all branches + run: git fetch --all + + - name: Reset stable branch to match release branch + run: | + git checkout -B stable origin/${GITHUB_REF#refs/heads/} + git push origin stable --force From f4afc98c7017b91771456f3617357cd999a16669 Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Wed, 5 Feb 2025 11:03:02 -0500 Subject: [PATCH 03/30] chore: Remove java release from publish workflow (#5016) * chore: Graduating some maintainers to Emeritus Signed-off-by: Francisco Javier Arceo * chore: Removing Java SDK Publish as it has been broken for several releases and no one has inquired about it Signed-off-by: Francisco Javier Arceo * removing maintainers file change Signed-off-by: Francisco Javier Arceo --------- Signed-off-by: Francisco Javier Arceo --- .github/workflows/publish.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 85c7c0e9141..3526ef4cd7b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -50,11 +50,3 @@ jobs: with: custom_version: ${{ github.event.inputs.custom_version }} token: ${{ github.event.inputs.token }} - - publish-java-sdk: - uses: ./.github/workflows/publish_java_sdk.yml - needs: [ publish-python-sdk ] - secrets: inherit - with: - custom_version: ${{ github.event.inputs.custom_version }} - token: ${{ github.event.inputs.token }} From 3194a110c2ad28e3f733fd18f718d86bc76da297 Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Wed, 5 Feb 2025 11:08:46 -0500 Subject: [PATCH 04/30] chore: Graduating some maintainers to Emeritus (#5014) Signed-off-by: Francisco Javier Arceo --- community/maintainers.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/community/maintainers.md b/community/maintainers.md index 5ccd347be00..d6da2a3e0ae 100644 --- a/community/maintainers.md +++ b/community/maintainers.md @@ -9,29 +9,29 @@ In alphabetical order | Name | GitHub Username | Email | Organization | | -------------- | ---------------- |-----------------------------| ------------------ | | Achal Shah | `achals` | achals@gmail.com | Tecton | -| Edson Tirelli | `etirelli` | ed.tirelli@gmail.com | Red Hat | | Francisco Javier Arceo | `franciscojavierarceo` | arceofrancisco@gmail.com | Affirm | | Hao Xu | `HaoXuAI` | sduxuhao@gmail.com | JPMorgan | -| Jeremy Ary | `jeremyary` | jeremy.ary@gmail.com | Red Hat | | Shuchu Han | `shuchu` | shuchu.han@gmail.com | Independent | | Willem Pienaar | `woop` | will.pienaar@gmail.com | Cleric | -| Zhiling Chen | `zhilingc` | chnzhlng@gmail.com | GetGround | -| Tornike Gurgenidze | `tokoko` | togurgenidze@gmail.com | Bank of Georgia | ## Emeritus Maintainers -| Name | GitHub Username | Email | Organization | -|---------------------|-----------------|-----------------------------|-------------------| -| Oleg Avdeev | oavdeev | oleg.v.avdeev@gmail.com | Tecton | -| Oleksii Moskalenko | pyalex | moskalenko.alexey@gmail.com | Tecton | -| Jay Parthasarthy | jparthasarthy | jparthasarthy@gmail.com | Tecton | -| Danny Chiao | adchia | danny@tecton.ai | Tecton | -| Pradithya Aria Pura | pradithya | pradithya.aria@gmail.com | Gojek | -| Tsotne Tabidze | tsotnet | tsotnet@gmail.com | Tecton | -| Abhin Chhabra | chhabrakadabra | chhabra.abhin@gmail.com | Shopify | -| Danny Chiao | adchia | danny@tecton.ai | Tecton | -| David Liu | mavysavydav | davidyliuliu@gmail.com | Twitter | -| Matt Delacour | MattDelac | mdelacour@hey.com | Shopify | -| Miles Adkins | sfc-gh-madkins | miles.adkins@snowflake.com | Snowflake | -| Felix Wang | `felixwang9817` | wangfelix98@gmail.com | Tecton | -| Kevin Zhang | `kevjumba` | kevin.zhang.13499@gmail.com | Tecton | +| Name | GitHub Username | Email | Organization | +|---------------------|----------------|---------------------------|-------------------| +| Edson Tirelli | `etirelli` | ed.tirelli@gmail.com | Red Hat | +| Jeremy Ary | `jeremyary` | jeremy.ary@gmail.com | Red Hat | +| Zhiling Chen | `zhilingc` | chnzhlng@gmail.com | GetGround | +| Tornike Gurgenidze | `tokoko` | togurgenidze@gmail.com | Bank of Georgia | +| Oleg Avdeev | oavdeev | oleg.v.avdeev@gmail.com | Tecton | +| Oleksii Moskalenko | pyalex | moskalenko.alexey@gmail.com | Tecton | +| Jay Parthasarthy | jparthasarthy | jparthasarthy@gmail.com | Tecton | +| Danny Chiao | adchia | danny@tecton.ai | Tecton | +| Pradithya Aria Pura | pradithya | pradithya.aria@gmail.com | Gojek | +| Tsotne Tabidze | tsotnet | tsotnet@gmail.com | Tecton | +| Abhin Chhabra | chhabrakadabra | chhabra.abhin@gmail.com | Shopify | +| Danny Chiao | adchia | danny@tecton.ai | Tecton | +| David Liu | mavysavydav | davidyliuliu@gmail.com | Twitter | +| Matt Delacour | MattDelac | mdelacour@hey.com | Shopify | +| Miles Adkins | sfc-gh-madkins | miles.adkins@snowflake.com | Snowflake | +| Felix Wang | `felixwang9817` | wangfelix98@gmail.com | Tecton | +| Kevin Zhang | `kevjumba` | kevin.zhang.13499@gmail.com | Tecton | From 2a9585ae3332ae300a5f58cf220cc0f48f23fa49 Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Wed, 5 Feb 2025 11:11:37 -0500 Subject: [PATCH 05/30] chore: Update release docs (#5015) * chore: Graduating some maintainers to Emeritus Signed-off-by: Francisco Javier Arceo * chore: Updating release docs with overview of process Signed-off-by: Francisco Javier Arceo * removing maintainers file change Signed-off-by: Francisco Javier Arceo * fix formatting Signed-off-by: Francisco Javier Arceo * fix link Signed-off-by: Francisco Javier Arceo * removing java release Signed-off-by: Francisco Javier Arceo --------- Signed-off-by: Francisco Javier Arceo --- docs/project/release-process.md | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/project/release-process.md b/docs/project/release-process.md index 251b9338f0a..becd0695cbb 100644 --- a/docs/project/release-process.md +++ b/docs/project/release-process.md @@ -1,5 +1,44 @@ # Release process +The release process is automated through a GitHub Action called [release.yml](https://github.com/feast-dev/feast/blob/master/.github/workflows/release.yml). +Here's a diagram of the workflows: + +```mermaid +graph LR + A[get_dry_release_versions] --> B[validate_version_bumps] + B --> C[publish-web-ui-npm] + C --> D[release] +``` + +The release step will trigger an automated chore commit by the CI-bot ([example](https://github.com/feast-dev/feast/commit/121617053344117cdbfbb480882b10cc176245ac)). + +After the `release` step and release commit, the `publish` step will be triggered ([example](https://github.com/feast-dev/feast/actions/runs/13143995111)). + +The `publish` worfklow triggers this flow: + +```mermaid +graph TD + A[publish.yml] -->|triggers| B[publish_python_sdk.yml] + B -->|needs| C[publish_images.yml] + B -->|needs| D[publish_helm_charts.yml] + B -->|needs| E[publish_java_sdk.yml] + + subgraph B[publish_python_sdk.yml] + direction LR + B1[Checkout code] --> B2[Set up Python] --> B3[Install dependencies] --> B4[Run tests] --> B5[Build wheels] --> B6[Publish to PyPI] + end + + subgraph C[publish_images.yml] + direction LR + C1[Checkout code] --> C2[Set up Docker] --> C3[Build Docker images] --> C4[Push Docker images] + end + + subgraph D[publish_helm_charts.yml] + direction LR + D1[Checkout code] --> D2[Set up Helm] --> D3[Package Helm charts] --> D4[Publish Helm charts] + end +``` + ## Release process For Feast maintainers, these are the concrete steps for making a new release. From 355da168a3ed36095144252c1a277c8d7b2af7b0 Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Wed, 5 Feb 2025 11:13:11 -0500 Subject: [PATCH 06/30] chore: Update release-process.md fixing --- docs/project/release-process.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/project/release-process.md b/docs/project/release-process.md index becd0695cbb..2cddca508cf 100644 --- a/docs/project/release-process.md +++ b/docs/project/release-process.md @@ -21,7 +21,6 @@ graph TD A[publish.yml] -->|triggers| B[publish_python_sdk.yml] B -->|needs| C[publish_images.yml] B -->|needs| D[publish_helm_charts.yml] - B -->|needs| E[publish_java_sdk.yml] subgraph B[publish_python_sdk.yml] direction LR From ea1d02dffaff9bf47a717c1646e45ebc25913b0d Mon Sep 17 00:00:00 2001 From: Abdul Hameed Date: Wed, 5 Feb 2025 16:15:25 -0500 Subject: [PATCH 07/30] chore: Added component_metadata file to show Feast latest release in ODH operator (#5021) added component_metadata file to show feast latest release in ODH operator Signed-off-by: Abdul Hameed --- infra/feast-operator/config/component_metadata.yaml | 5 +++++ infra/scripts/release/files_to_bump.txt | 1 + 2 files changed, 6 insertions(+) create mode 100644 infra/feast-operator/config/component_metadata.yaml diff --git a/infra/feast-operator/config/component_metadata.yaml b/infra/feast-operator/config/component_metadata.yaml new file mode 100644 index 00000000000..d4c7621f471 --- /dev/null +++ b/infra/feast-operator/config/component_metadata.yaml @@ -0,0 +1,5 @@ +# This file is required to configure Feast release information for ODH/RHOAI Operator +releases: + - name: Feast + version: 0.45.0 + repoUrl: https://github.com/feast-dev/feast diff --git a/infra/scripts/release/files_to_bump.txt b/infra/scripts/release/files_to_bump.txt index 0ee09ea2c1f..7cb9dd1e8e4 100644 --- a/infra/scripts/release/files_to_bump.txt +++ b/infra/scripts/release/files_to_bump.txt @@ -14,6 +14,7 @@ infra/feast-helm-operator/Makefile 6 infra/feast-helm-operator/config/manager/kustomization.yaml 8 infra/feast-operator/Makefile 6 infra/feast-operator/config/manager/kustomization.yaml 8 +infra/feast-operator/config/component_metadata.yaml 4 infra/feast-operator/config/overlays/odh/params.env 1 2 infra/feast-operator/api/feastversion/version.go 20 java/pom.xml 38 From fce0d35bc00553269fff6abb7a16897577a2421f Mon Sep 17 00:00:00 2001 From: Theodor Mihalache <84387487+tmihalac@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:46:54 -0500 Subject: [PATCH 08/30] fix: Changed feast operator to set status of featurestore cr to ready based on deployment.status = available (#5020) Changed featurestore cr ready status to reflect deployment available status Signed-off-by: Theodor Mihalache --- .../api/v1alpha1/featurestore_types.go | 32 +++++++++-------- .../controller/featurestore_controller.go | 24 +++++++++++++ .../featurestore_controller_db_store_test.go | 8 ++--- .../featurestore_controller_ephemeral_test.go | 8 ++--- ...restore_controller_kubernetes_auth_test.go | 8 ++--- .../featurestore_controller_loglevel_test.go | 8 ++--- ...eaturestore_controller_objectstore_test.go | 8 ++--- .../featurestore_controller_oidc_auth_test.go | 8 ++--- .../featurestore_controller_pvc_test.go | 8 ++--- .../featurestore_controller_test.go | 34 ++++++++++++++++--- .../featurestore_controller_tls_test.go | 8 ++--- .../internal/controller/services/services.go | 17 ++++++++++ 12 files changed, 119 insertions(+), 52 deletions(-) diff --git a/infra/feast-operator/api/v1alpha1/featurestore_types.go b/infra/feast-operator/api/v1alpha1/featurestore_types.go index 83ba2067741..19b13be8c55 100644 --- a/infra/feast-operator/api/v1alpha1/featurestore_types.go +++ b/infra/feast-operator/api/v1alpha1/featurestore_types.go @@ -38,23 +38,25 @@ const ( AuthorizationReadyType = "Authorization" // Feast condition reasons: - ReadyReason = "Ready" - FailedReason = "FeatureStoreFailed" - OfflineStoreFailedReason = "OfflineStoreDeploymentFailed" - OnlineStoreFailedReason = "OnlineStoreDeploymentFailed" - RegistryFailedReason = "RegistryDeploymentFailed" - UIFailedReason = "UIDeploymentFailed" - ClientFailedReason = "ClientDeploymentFailed" - KubernetesAuthzFailedReason = "KubernetesAuthorizationDeploymentFailed" + ReadyReason = "Ready" + FailedReason = "FeatureStoreFailed" + DeploymentNotAvailableReason = "DeploymentNotAvailable" + OfflineStoreFailedReason = "OfflineStoreDeploymentFailed" + OnlineStoreFailedReason = "OnlineStoreDeploymentFailed" + RegistryFailedReason = "RegistryDeploymentFailed" + UIFailedReason = "UIDeploymentFailed" + ClientFailedReason = "ClientDeploymentFailed" + KubernetesAuthzFailedReason = "KubernetesAuthorizationDeploymentFailed" // Feast condition messages: - ReadyMessage = "FeatureStore installation complete" - OfflineStoreReadyMessage = "Offline Store installation complete" - OnlineStoreReadyMessage = "Online Store installation complete" - RegistryReadyMessage = "Registry installation complete" - UIReadyMessage = "UI installation complete" - ClientReadyMessage = "Client installation complete" - KubernetesAuthzReadyMessage = "Kubernetes authorization installation complete" + ReadyMessage = "FeatureStore installation complete" + OfflineStoreReadyMessage = "Offline Store installation complete" + OnlineStoreReadyMessage = "Online Store installation complete" + RegistryReadyMessage = "Registry installation complete" + UIReadyMessage = "UI installation complete" + ClientReadyMessage = "Client installation complete" + KubernetesAuthzReadyMessage = "Kubernetes authorization installation complete" + DeploymentNotAvailableMessage = "Deployment is not available" // entity_key_serialization_version SerializationVersion = 3 diff --git a/infra/feast-operator/internal/controller/featurestore_controller.go b/infra/feast-operator/internal/controller/featurestore_controller.go index 90248ff3de0..c3353c859f8 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller.go +++ b/infra/feast-operator/internal/controller/featurestore_controller.go @@ -138,6 +138,30 @@ func (r *FeatureStoreReconciler) deployFeast(ctx context.Context, cr *feastdevv1 Reason: feastdevv1alpha1.FailedReason, Message: "Error: " + err.Error(), } + } else { + deployment, deploymentErr := feast.GetDeployment() + if deploymentErr != nil { + condition = metav1.Condition{ + Type: feastdevv1alpha1.ReadyType, + Status: metav1.ConditionUnknown, + Reason: feastdevv1alpha1.DeploymentNotAvailableReason, + Message: feastdevv1alpha1.DeploymentNotAvailableMessage, + } + + result = errResult + } else { + isDeployAvailable := services.IsDeploymentAvailable(deployment.Status.Conditions) + if !isDeployAvailable { + condition = metav1.Condition{ + Type: feastdevv1alpha1.ReadyType, + Status: metav1.ConditionUnknown, + Reason: feastdevv1alpha1.DeploymentNotAvailableReason, + Message: feastdevv1alpha1.DeploymentNotAvailableMessage, + } + + result = errResult + } + } } logger.Info(condition.Message) 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 d6ae16443f7..a379c33ff14 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 @@ -398,10 +398,10 @@ var _ = Describe("FeatureStore Controller - db storage services", func() { Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) Expect(cond).ToNot(BeNil()) - Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(feastdevv1alpha1.DeploymentNotAvailableReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.DeploymentNotAvailableMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) Expect(cond).ToNot(BeNil()) @@ -431,7 +431,7 @@ var _ = Describe("FeatureStore Controller - db storage services", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.OnlineStoreReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.OnlineStoreReadyMessage)) - Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.ReadyPhase)) + Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) // check deployment deploy := &appsv1.Deployment{} 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 c9e270b040d..06d0cd3466e 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go @@ -164,10 +164,10 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) Expect(cond).ToNot(BeNil()) - Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(feastdevv1alpha1.DeploymentNotAvailableReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.DeploymentNotAvailableMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) @@ -200,7 +200,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.OnlineStoreReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.OnlineStoreReadyMessage)) - Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.ReadyPhase)) + Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) // check deployment deploy := &appsv1.Deployment{} 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 c0c02a96148..9003fb83d52 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 @@ -150,10 +150,10 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) Expect(cond).ToNot(BeNil()) - Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(feastdevv1alpha1.DeploymentNotAvailableReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.DeploymentNotAvailableMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).ToNot(BeNil()) @@ -190,7 +190,7 @@ var _ = Describe("FeatureStore Controller-Kubernetes authorization", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.OnlineStoreReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.OnlineStoreReadyMessage)) - Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.ReadyPhase)) + Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) // check deployment deploy := &appsv1.Deployment{} 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 f3500dec084..bdd1d867319 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_loglevel_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_loglevel_test.go @@ -129,10 +129,10 @@ var _ = Describe("FeatureStore Controller - Feast service LogLevel", func() { Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) Expect(cond).ToNot(BeNil()) - Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(feastdevv1alpha1.DeploymentNotAvailableReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.DeploymentNotAvailableMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) Expect(cond).ToNot(BeNil()) @@ -161,7 +161,7 @@ var _ = Describe("FeatureStore Controller - Feast service LogLevel", func() { Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.OnlineStoreReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.OnlineStoreReadyMessage)) - Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.ReadyPhase)) + Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) // check deployment deploy := &appsv1.Deployment{} 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 85a30e79432..12ab5cc4d91 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go @@ -148,10 +148,10 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) Expect(cond).ToNot(BeNil()) - Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(feastdevv1alpha1.DeploymentNotAvailableReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.DeploymentNotAvailableMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) @@ -176,7 +176,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.OnlineStoreReadyType) Expect(cond).To(BeNil()) - Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.ReadyPhase)) + Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) // check deployment deploy := &appsv1.Deployment{} 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 cf2ea78cdf0..590f7335d25 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 @@ -173,10 +173,10 @@ var _ = Describe("FeatureStore Controller-OIDC authorization", func() { Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) Expect(cond).ToNot(BeNil()) - Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(feastdevv1alpha1.DeploymentNotAvailableReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.DeploymentNotAvailableMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) @@ -209,7 +209,7 @@ var _ = Describe("FeatureStore Controller-OIDC authorization", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.OnlineStoreReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.OnlineStoreReadyMessage)) - Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.ReadyPhase)) + Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) // check deployment deploy := &appsv1.Deployment{} 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 94bc0df3796..488b0661661 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go @@ -227,10 +227,10 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) Expect(cond).ToNot(BeNil()) - Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(feastdevv1alpha1.DeploymentNotAvailableReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.DeploymentNotAvailableMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) @@ -263,7 +263,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.OnlineStoreReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.OnlineStoreReadyMessage)) - Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.ReadyPhase)) + Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) ephemeralName := "feast-data" ephemeralVolume := corev1.Volume{ diff --git a/infra/feast-operator/internal/controller/featurestore_controller_test.go b/infra/feast-operator/internal/controller/featurestore_controller_test.go index 152bd0b18f0..c3512dd7837 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_test.go @@ -127,6 +127,31 @@ var _ = Describe("FeatureStore Controller", func() { FeatureStore: resource, }, } + + deployment, _ := feast.GetDeployment() + deployment.Status = appsv1.DeploymentStatus{ + Conditions: []appsv1.DeploymentCondition{ + { + Type: appsv1.DeploymentAvailable, + Status: "True", // Mark as available + Reason: "MinimumReplicasAvailable", + }, + }, + } + + // Update the deployment's status + err = controllerReconciler.Status().Update(context.Background(), &deployment) + Expect(err).NotTo(HaveOccurred()) + + _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + + resource = &feastdevv1alpha1.FeatureStore{} + err = k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + Expect(resource.Status).NotTo(BeNil()) Expect(resource.Status.FeastVersion).To(Equal(feastversion.FeastVersion)) Expect(resource.Status.ClientConfigMap).To(Equal(feast.GetFeastServiceName(services.ClientFeastType))) @@ -501,10 +526,10 @@ var _ = Describe("FeatureStore Controller", func() { Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) Expect(cond).ToNot(BeNil()) - Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(feastdevv1alpha1.DeploymentNotAvailableReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.DeploymentNotAvailableMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) @@ -544,7 +569,7 @@ var _ = Describe("FeatureStore Controller", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.UIReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.UIReadyMessage)) - Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.ReadyPhase)) + Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) deploy := &appsv1.Deployment{} objMeta := feast.GetObjectMeta() @@ -999,7 +1024,6 @@ var _ = Describe("FeatureStore Controller", func() { Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType)).To(BeNil()) Expect(apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType)).To(BeNil()) - Expect(apimeta.IsStatusConditionTrue(resource.Status.Conditions, feastdevv1alpha1.ReadyType)).To(BeTrue()) Expect(apimeta.IsStatusConditionTrue(resource.Status.Conditions, feastdevv1alpha1.OnlineStoreReadyType)).To(BeTrue()) Expect(apimeta.IsStatusConditionTrue(resource.Status.Conditions, feastdevv1alpha1.OfflineStoreReadyType)).To(BeTrue()) Expect(resource.Status.ServiceHostnames.Registry).ToNot(BeEmpty()) 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 76298ce40a0..60d6b2224fa 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go @@ -145,10 +145,10 @@ var _ = Describe("FeatureStore Controller - Feast service TLS", func() { Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) Expect(cond).ToNot(BeNil()) - Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(feastdevv1alpha1.DeploymentNotAvailableReason)) Expect(cond.Type).To(Equal(feastdevv1alpha1.ReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.ReadyMessage)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.DeploymentNotAvailableMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) Expect(cond).ToNot(BeNil()) @@ -178,7 +178,7 @@ var _ = Describe("FeatureStore Controller - Feast service TLS", func() { Expect(cond.Type).To(Equal(feastdevv1alpha1.OnlineStoreReadyType)) Expect(cond.Message).To(Equal(feastdevv1alpha1.OnlineStoreReadyMessage)) - Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.ReadyPhase)) + Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) // check deployment deploy := &appsv1.Deployment{} diff --git a/infra/feast-operator/internal/controller/services/services.go b/infra/feast-operator/internal/controller/services/services.go index 4bf37e86dbf..cc7d1d215fb 100644 --- a/infra/feast-operator/internal/controller/services/services.go +++ b/infra/feast-operator/internal/controller/services/services.go @@ -614,6 +614,13 @@ func (feast *FeastServices) GetFeastServiceName(feastType FeastServiceType) stri return GetFeastServiceName(feast.Handler.FeatureStore, feastType) } +func (feast *FeastServices) GetDeployment() (appsv1.Deployment, error) { + deployment := appsv1.Deployment{} + obj := feast.GetObjectMeta() + err := feast.Handler.Get(feast.Handler.Context, client.ObjectKey{Namespace: obj.GetNamespace(), Name: obj.GetName()}, &deployment) + return deployment, err +} + // GetFeastServiceName returns the feast service object name based on service type func GetFeastServiceName(featureStore *feastdevv1alpha1.FeatureStore, feastType FeastServiceType) string { return GetFeastName(featureStore) + "-" + string(feastType) @@ -917,3 +924,13 @@ func getProbeHandler(feastType FeastServiceType, tls *feastdevv1alpha1.TlsConfig }, } } + +func IsDeploymentAvailable(conditions []appsv1.DeploymentCondition) bool { + for _, condition := range conditions { + if condition.Type == appsv1.DeploymentAvailable { + return condition.Status == corev1.ConditionTrue + } + } + + return false +} From f4afcd2e9bb831e412dd31327b8596961422be5a Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Thu, 6 Feb 2025 13:59:44 -0500 Subject: [PATCH 09/30] docs: Adding docs and retrieve online documents endpoint to Feature Server documentation (#5019) Signed-off-by: Francisco Javier Arceo --- docs/getting-started/components/feature-server.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/getting-started/components/feature-server.md b/docs/getting-started/components/feature-server.md index 90e6d25e5a2..4d961054ecb 100644 --- a/docs/getting-started/components/feature-server.md +++ b/docs/getting-started/components/feature-server.md @@ -31,10 +31,12 @@ The Feature Server operates as a stateless service backed by two key components: ## Endpoints Overview -| Endpoint | Description | -| -------------------------- | ----------------------------------------------------------------------- | -| `/get-online-features` | Retrieves feature values for specified entities and feature references. | -| `/push` | Pushes feature data to the online and/or offline store. | -| `/materialize` | Materializes features within a specific time range to the online store. | -| `/materialize-incremental` | Incrementally materializes features up to the current timestamp. | +| Endpoint | Description | +|------------------------------|-------------------------------------------------------------------------| +| `/get-online-features` | Retrieves feature values for specified entities and feature references. | +| `/push` | Pushes feature data to the online and/or offline store. | +| `/materialize` | Materializes features within a specific time range to the online store. | +| `/materialize-incremental` | Incrementally materializes features up to the current timestamp. | +| `/retrieve-online-documents` | Supports Vector Similarity Search for RAG (Alpha end-ponit) | +| `/docs` | API Contract for available endpoints | From 358677814b9743e1fd908612b16700f7483c24f8 Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Thu, 6 Feb 2025 21:47:04 -0500 Subject: [PATCH 10/30] chore: Add Tornike and Zhiling back as maintainers (#5017) --- community/maintainers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/community/maintainers.md b/community/maintainers.md index d6da2a3e0ae..779689851d7 100644 --- a/community/maintainers.md +++ b/community/maintainers.md @@ -13,6 +13,8 @@ In alphabetical order | Hao Xu | `HaoXuAI` | sduxuhao@gmail.com | JPMorgan | | Shuchu Han | `shuchu` | shuchu.han@gmail.com | Independent | | Willem Pienaar | `woop` | will.pienaar@gmail.com | Cleric | +| Zhiling Chen | `zhilingc` | chnzhlng@gmail.com | GetGround | +| Tornike Gurgenidze | `tokoko` | togurgenidze@gmail.com | Bank of Georgia | ## Emeritus Maintainers @@ -20,8 +22,6 @@ In alphabetical order |---------------------|----------------|---------------------------|-------------------| | Edson Tirelli | `etirelli` | ed.tirelli@gmail.com | Red Hat | | Jeremy Ary | `jeremyary` | jeremy.ary@gmail.com | Red Hat | -| Zhiling Chen | `zhilingc` | chnzhlng@gmail.com | GetGround | -| Tornike Gurgenidze | `tokoko` | togurgenidze@gmail.com | Bank of Georgia | | Oleg Avdeev | oavdeev | oleg.v.avdeev@gmail.com | Tecton | | Oleksii Moskalenko | pyalex | moskalenko.alexey@gmail.com | Tecton | | Jay Parthasarthy | jparthasarthy | jparthasarthy@gmail.com | Tecton | From 5a17b683f3a6c9a47e0b5e44aa1d063491b6011e Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Thu, 6 Feb 2025 22:20:56 -0500 Subject: [PATCH 11/30] chore: Updating sqlite-vec (#5027) Signed-off-by: Francisco Javier Arceo --- .../requirements/py3.10-ci-requirements.txt | 51 ++++++++++--------- .../requirements/py3.10-requirements.txt | 12 ++--- .../requirements/py3.11-ci-requirements.txt | 51 ++++++++++--------- .../requirements/py3.11-requirements.txt | 12 ++--- .../requirements/py3.9-ci-requirements.txt | 49 +++++++++--------- .../requirements/py3.9-requirements.txt | 12 ++--- setup.py | 2 +- 7 files changed, 99 insertions(+), 90 deletions(-) diff --git a/sdk/python/requirements/py3.10-ci-requirements.txt b/sdk/python/requirements/py3.10-ci-requirements.txt index eae0a088fbc..96948e78e23 100644 --- a/sdk/python/requirements/py3.10-ci-requirements.txt +++ b/sdk/python/requirements/py3.10-ci-requirements.txt @@ -4,7 +4,7 @@ aiobotocore==2.19.0 # via feast (setup.py) aiohappyeyeballs==2.4.4 # via aiohttp -aiohttp==3.11.11 +aiohttp==3.11.12 # via aiobotocore aioitertools==0.12.0 # via aiobotocore @@ -61,11 +61,11 @@ azure-identity==1.19.0 # via feast (setup.py) azure-storage-blob==12.24.1 # via feast (setup.py) -babel==2.16.0 +babel==2.17.0 # via # jupyterlab-server # sphinx -beautifulsoup4==4.12.3 +beautifulsoup4==4.13.3 # via nbconvert bigtree==0.23.1 # via feast (setup.py) @@ -90,7 +90,7 @@ cachetools==5.5.1 # via google-auth cassandra-driver==3.29.2 # via feast (setup.py) -certifi==2024.12.14 +certifi==2025.1.31 # via # elastic-transport # httpcore @@ -150,7 +150,7 @@ cython==3.0.11 # via thriftpy2 dask[dataframe]==2025.1.0 # via feast (setup.py) -db-dtypes==1.4.0 +db-dtypes==1.4.1 # via google-cloud-bigquery debugpy==1.8.12 # via ipykernel @@ -189,9 +189,9 @@ execnet==2.1.1 # via pytest-xdist executing==2.2.0 # via stack-data -faiss-cpu==1.9.0.post1 +faiss-cpu==1.10.0 # via feast (setup.py) -fastapi==0.115.7 +fastapi==0.115.8 # via feast (setup.py) fastjsonschema==2.21.1 # via nbformat @@ -232,7 +232,7 @@ google-auth==2.38.0 # kubernetes google-cloud-bigquery[pandas]==3.29.0 # via feast (setup.py) -google-cloud-bigquery-storage==2.27.0 +google-cloud-bigquery-storage==2.28.0 # via feast (setup.py) google-cloud-bigtable==2.28.1 # via feast (setup.py) @@ -297,7 +297,7 @@ h11==0.14.0 # via # httpcore # uvicorn -h2==4.1.0 +h2==4.2.0 # via httpx happybase==1.2.0 # via feast (setup.py) @@ -345,7 +345,7 @@ iniconfig==2.0.0 # via pytest ipykernel==6.29.5 # via jupyterlab -ipython==8.31.0 +ipython==8.32.0 # via # great-expectations # ipykernel @@ -406,7 +406,7 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat -jupyter-events==0.11.0 +jupyter-events==0.12.0 # via jupyter-server jupyter-lsp==2.2.5 # via jupyterlab @@ -419,7 +419,7 @@ jupyter-server==2.15.0 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.3.4 +jupyterlab==4.3.5 # via notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -446,7 +446,7 @@ markupsafe==3.0.2 # jinja2 # nbconvert # werkzeug -marshmallow==3.26.0 +marshmallow==3.26.1 # via # environs # great-expectations @@ -460,7 +460,7 @@ milvus-lite==2.4.11 # via pymilvus minio==7.2.11 # via feast (setup.py) -mistune==3.1.0 +mistune==3.1.1 # via # great-expectations # nbconvert @@ -491,7 +491,7 @@ mypy-protobuf==3.3.0 # via feast (setup.py) nbclient==0.10.2 # via nbconvert -nbconvert==7.16.5 +nbconvert==7.16.6 # via jupyter-server nbformat==5.10.4 # via @@ -539,6 +539,7 @@ packaging==24.2 # ibis-framework # ibis-substrait # ipykernel + # jupyter-events # jupyter-server # jupyterlab # jupyterlab-server @@ -568,7 +569,7 @@ parsy==2.1 # via ibis-framework partd==1.4.2 # via dask -pbr==6.1.0 +pbr==6.1.1 # via mock pexpect==4.9.0 # via ipython @@ -760,7 +761,7 @@ python-json-logger==3.2.1 # via jupyter-events python-keycloak==4.2.2 # via feast (setup.py) -pytz==2024.2 +pytz==2025.1 # via # great-expectations # ibis-framework @@ -777,7 +778,7 @@ pyyaml==6.0.2 # pre-commit # responses # uvicorn -pyzmq==26.2.0 +pyzmq==26.2.1 # via # ipykernel # jupyter-client @@ -842,7 +843,7 @@ ruamel-yaml==0.17.40 # via great-expectations ruamel-yaml-clib==0.2.12 # via ruamel-yaml -ruff==0.9.3 +ruff==0.9.5 # via feast (setup.py) s3transfer==0.11.2 # via boto3 @@ -855,6 +856,7 @@ setuptools==75.8.0 # grpcio-tools # jupyterlab # kubernetes + # pbr # pip-tools # pymilvus # singlestoredb @@ -876,7 +878,7 @@ sniffio==1.3.1 # httpx snowballstemmer==2.2.0 # via sphinx -snowflake-connector-python[pandas]==3.13.0 +snowflake-connector-python[pandas]==3.13.2 # via feast (setup.py) sortedcontainers==2.4.0 # via snowflake-connector-python @@ -896,11 +898,11 @@ sphinxcontrib-qthelp==2.0.0 # via sphinx sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy[mypy]==2.0.37 +sqlalchemy[mypy]==2.0.38 # via feast (setup.py) sqlglot==25.20.2 # via ibis-framework -sqlite-vec==0.1.1 +sqlite-vec==0.1.6 # via feast (setup.py) sqlparams==6.2.0 # via singlestoredb @@ -972,7 +974,7 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat -trino==0.332.0 +trino==0.333.0 # via feast (setup.py) typeguard==4.4.1 # via feast (setup.py) @@ -990,7 +992,7 @@ types-python-dateutil==2.9.0.20241206 # via # feast (setup.py) # arrow -types-pytz==2024.2.0.20241221 +types-pytz==2025.1.0.20250204 # via feast (setup.py) types-pyyaml==6.0.12.20241230 # via feast (setup.py) @@ -1013,6 +1015,7 @@ typing-extensions==4.12.2 # azure-core # azure-identity # azure-storage-blob + # beautifulsoup4 # fastapi # great-expectations # ibis-framework diff --git a/sdk/python/requirements/py3.10-requirements.txt b/sdk/python/requirements/py3.10-requirements.txt index 7e873fc510e..c25bda58b7e 100644 --- a/sdk/python/requirements/py3.10-requirements.txt +++ b/sdk/python/requirements/py3.10-requirements.txt @@ -12,7 +12,7 @@ attrs==25.1.0 # referencing bigtree==0.23.1 # via feast (setup.py) -certifi==2024.12.14 +certifi==2025.1.31 # via requests charset-normalizer==3.4.1 # via requests @@ -31,9 +31,9 @@ dill==0.3.9 # via feast (setup.py) exceptiongroup==1.2.2 # via anyio -fastapi==0.115.7 +fastapi==0.115.8 # via feast (setup.py) -fsspec==2024.12.0 +fsspec==2025.2.0 # via dask gunicorn==23.0.0 # via @@ -61,7 +61,7 @@ markupsafe==3.0.2 # via jinja2 mmh3==5.1.0 # via feast (setup.py) -mypy==1.14.1 +mypy==1.15.0 # via sqlalchemy mypy-extensions==1.0.0 # via mypy @@ -104,7 +104,7 @@ python-dateutil==2.9.0.post0 # via pandas python-dotenv==1.0.1 # via uvicorn -pytz==2024.2 +pytz==2025.1 # via pandas pyyaml==6.0.2 # via @@ -125,7 +125,7 @@ six==1.17.0 # via python-dateutil sniffio==1.3.1 # via anyio -sqlalchemy[mypy]==2.0.37 +sqlalchemy[mypy]==2.0.38 # via feast (setup.py) starlette==0.45.3 # via fastapi diff --git a/sdk/python/requirements/py3.11-ci-requirements.txt b/sdk/python/requirements/py3.11-ci-requirements.txt index c8b7d34d7e2..20976b02045 100644 --- a/sdk/python/requirements/py3.11-ci-requirements.txt +++ b/sdk/python/requirements/py3.11-ci-requirements.txt @@ -4,7 +4,7 @@ aiobotocore==2.19.0 # via feast (setup.py) aiohappyeyeballs==2.4.4 # via aiohttp -aiohttp==3.11.11 +aiohttp==3.11.12 # via aiobotocore aioitertools==0.12.0 # via aiobotocore @@ -59,11 +59,11 @@ azure-identity==1.19.0 # via feast (setup.py) azure-storage-blob==12.24.1 # via feast (setup.py) -babel==2.16.0 +babel==2.17.0 # via # jupyterlab-server # sphinx -beautifulsoup4==4.12.3 +beautifulsoup4==4.13.3 # via nbconvert bigtree==0.23.1 # via feast (setup.py) @@ -88,7 +88,7 @@ cachetools==5.5.1 # via google-auth cassandra-driver==3.29.2 # via feast (setup.py) -certifi==2024.12.14 +certifi==2025.1.31 # via # elastic-transport # httpcore @@ -148,7 +148,7 @@ cython==3.0.11 # via thriftpy2 dask[dataframe]==2025.1.0 # via feast (setup.py) -db-dtypes==1.4.0 +db-dtypes==1.4.1 # via google-cloud-bigquery debugpy==1.8.12 # via ipykernel @@ -182,9 +182,9 @@ execnet==2.1.1 # via pytest-xdist executing==2.2.0 # via stack-data -faiss-cpu==1.9.0.post1 +faiss-cpu==1.10.0 # via feast (setup.py) -fastapi==0.115.7 +fastapi==0.115.8 # via feast (setup.py) fastjsonschema==2.21.1 # via nbformat @@ -225,7 +225,7 @@ google-auth==2.38.0 # kubernetes google-cloud-bigquery[pandas]==3.29.0 # via feast (setup.py) -google-cloud-bigquery-storage==2.27.0 +google-cloud-bigquery-storage==2.28.0 # via feast (setup.py) google-cloud-bigtable==2.28.1 # via feast (setup.py) @@ -290,7 +290,7 @@ h11==0.14.0 # via # httpcore # uvicorn -h2==4.1.0 +h2==4.2.0 # via httpx happybase==1.2.0 # via feast (setup.py) @@ -336,7 +336,7 @@ iniconfig==2.0.0 # via pytest ipykernel==6.29.5 # via jupyterlab -ipython==8.31.0 +ipython==8.32.0 # via # great-expectations # ipykernel @@ -397,7 +397,7 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat -jupyter-events==0.11.0 +jupyter-events==0.12.0 # via jupyter-server jupyter-lsp==2.2.5 # via jupyterlab @@ -410,7 +410,7 @@ jupyter-server==2.15.0 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.3.4 +jupyterlab==4.3.5 # via notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -437,7 +437,7 @@ markupsafe==3.0.2 # jinja2 # nbconvert # werkzeug -marshmallow==3.26.0 +marshmallow==3.26.1 # via # environs # great-expectations @@ -451,7 +451,7 @@ milvus-lite==2.4.11 # via pymilvus minio==7.2.11 # via feast (setup.py) -mistune==3.1.0 +mistune==3.1.1 # via # great-expectations # nbconvert @@ -482,7 +482,7 @@ mypy-protobuf==3.3.0 # via feast (setup.py) nbclient==0.10.2 # via nbconvert -nbconvert==7.16.5 +nbconvert==7.16.6 # via jupyter-server nbformat==5.10.4 # via @@ -530,6 +530,7 @@ packaging==24.2 # ibis-framework # ibis-substrait # ipykernel + # jupyter-events # jupyter-server # jupyterlab # jupyterlab-server @@ -559,7 +560,7 @@ parsy==2.1 # via ibis-framework partd==1.4.2 # via dask -pbr==6.1.0 +pbr==6.1.1 # via mock pexpect==4.9.0 # via ipython @@ -751,7 +752,7 @@ python-json-logger==3.2.1 # via jupyter-events python-keycloak==4.2.2 # via feast (setup.py) -pytz==2024.2 +pytz==2025.1 # via # great-expectations # ibis-framework @@ -768,7 +769,7 @@ pyyaml==6.0.2 # pre-commit # responses # uvicorn -pyzmq==26.2.0 +pyzmq==26.2.1 # via # ipykernel # jupyter-client @@ -833,7 +834,7 @@ ruamel-yaml==0.17.40 # via great-expectations ruamel-yaml-clib==0.2.12 # via ruamel-yaml -ruff==0.9.3 +ruff==0.9.5 # via feast (setup.py) s3transfer==0.11.2 # via boto3 @@ -846,6 +847,7 @@ setuptools==75.8.0 # grpcio-tools # jupyterlab # kubernetes + # pbr # pip-tools # pymilvus # singlestoredb @@ -867,7 +869,7 @@ sniffio==1.3.1 # httpx snowballstemmer==2.2.0 # via sphinx -snowflake-connector-python[pandas]==3.13.0 +snowflake-connector-python[pandas]==3.13.2 # via feast (setup.py) sortedcontainers==2.4.0 # via snowflake-connector-python @@ -887,11 +889,11 @@ sphinxcontrib-qthelp==2.0.0 # via sphinx sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy[mypy]==2.0.37 +sqlalchemy[mypy]==2.0.38 # via feast (setup.py) sqlglot==25.20.2 # via ibis-framework -sqlite-vec==0.1.1 +sqlite-vec==0.1.6 # via feast (setup.py) sqlparams==6.2.0 # via singlestoredb @@ -953,7 +955,7 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat -trino==0.332.0 +trino==0.333.0 # via feast (setup.py) typeguard==4.4.1 # via feast (setup.py) @@ -971,7 +973,7 @@ types-python-dateutil==2.9.0.20241206 # via # feast (setup.py) # arrow -types-pytz==2024.2.0.20241221 +types-pytz==2025.1.0.20250204 # via feast (setup.py) types-pyyaml==6.0.12.20241230 # via feast (setup.py) @@ -993,6 +995,7 @@ typing-extensions==4.12.2 # azure-core # azure-identity # azure-storage-blob + # beautifulsoup4 # fastapi # great-expectations # ibis-framework diff --git a/sdk/python/requirements/py3.11-requirements.txt b/sdk/python/requirements/py3.11-requirements.txt index 09d29831c6f..f79776a9147 100644 --- a/sdk/python/requirements/py3.11-requirements.txt +++ b/sdk/python/requirements/py3.11-requirements.txt @@ -12,7 +12,7 @@ attrs==25.1.0 # referencing bigtree==0.23.1 # via feast (setup.py) -certifi==2024.12.14 +certifi==2025.1.31 # via requests charset-normalizer==3.4.1 # via requests @@ -29,9 +29,9 @@ dask[dataframe]==2025.1.0 # via feast (setup.py) dill==0.3.9 # via feast (setup.py) -fastapi==0.115.7 +fastapi==0.115.8 # via feast (setup.py) -fsspec==2024.12.0 +fsspec==2025.2.0 # via dask gunicorn==23.0.0 # via @@ -59,7 +59,7 @@ markupsafe==3.0.2 # via jinja2 mmh3==5.1.0 # via feast (setup.py) -mypy==1.14.1 +mypy==1.15.0 # via sqlalchemy mypy-extensions==1.0.0 # via mypy @@ -102,7 +102,7 @@ python-dateutil==2.9.0.post0 # via pandas python-dotenv==1.0.1 # via uvicorn -pytz==2024.2 +pytz==2025.1 # via pandas pyyaml==6.0.2 # via @@ -123,7 +123,7 @@ six==1.17.0 # via python-dateutil sniffio==1.3.1 # via anyio -sqlalchemy[mypy]==2.0.37 +sqlalchemy[mypy]==2.0.38 # via feast (setup.py) starlette==0.45.3 # via fastapi diff --git a/sdk/python/requirements/py3.9-ci-requirements.txt b/sdk/python/requirements/py3.9-ci-requirements.txt index 46984af1069..00eb59c93d2 100644 --- a/sdk/python/requirements/py3.9-ci-requirements.txt +++ b/sdk/python/requirements/py3.9-ci-requirements.txt @@ -4,7 +4,7 @@ aiobotocore==2.19.0 # via feast (setup.py) aiohappyeyeballs==2.4.4 # via aiohttp -aiohttp==3.11.11 +aiohttp==3.11.12 # via aiobotocore aioitertools==0.12.0 # via aiobotocore @@ -61,11 +61,11 @@ azure-identity==1.19.0 # via feast (setup.py) azure-storage-blob==12.24.1 # via feast (setup.py) -babel==2.16.0 +babel==2.17.0 # via # jupyterlab-server # sphinx -beautifulsoup4==4.12.3 +beautifulsoup4==4.13.3 # via nbconvert bidict==0.23.1 # via ibis-framework @@ -92,7 +92,7 @@ cachetools==5.5.1 # via google-auth cassandra-driver==3.29.2 # via feast (setup.py) -certifi==2024.12.14 +certifi==2025.1.31 # via # elastic-transport # httpcore @@ -156,7 +156,7 @@ dask[dataframe]==2024.8.0 # dask-expr dask-expr==1.1.10 # via dask -db-dtypes==1.4.0 +db-dtypes==1.4.1 # via google-cloud-bigquery debugpy==1.8.12 # via ipykernel @@ -195,9 +195,9 @@ execnet==2.1.1 # via pytest-xdist executing==2.2.0 # via stack-data -faiss-cpu==1.9.0.post1 +faiss-cpu==1.10.0 # via feast (setup.py) -fastapi==0.115.7 +fastapi==0.115.8 # via feast (setup.py) fastjsonschema==2.21.1 # via nbformat @@ -238,7 +238,7 @@ google-auth==2.38.0 # kubernetes google-cloud-bigquery[pandas]==3.29.0 # via feast (setup.py) -google-cloud-bigquery-storage==2.27.0 +google-cloud-bigquery-storage==2.28.0 # via feast (setup.py) google-cloud-bigtable==2.28.1 # via feast (setup.py) @@ -303,7 +303,7 @@ h11==0.14.0 # via # httpcore # uvicorn -h2==4.1.0 +h2==4.2.0 # via httpx happybase==1.2.0 # via feast (setup.py) @@ -419,7 +419,7 @@ jupyter-core==5.7.2 # nbclient # nbconvert # nbformat -jupyter-events==0.11.0 +jupyter-events==0.12.0 # via jupyter-server jupyter-lsp==2.2.5 # via jupyterlab @@ -432,7 +432,7 @@ jupyter-server==2.15.0 # notebook-shim jupyter-server-terminals==0.5.3 # via jupyter-server -jupyterlab==4.3.4 +jupyterlab==4.3.5 # via notebook jupyterlab-pygments==0.3.0 # via nbconvert @@ -459,7 +459,7 @@ markupsafe==3.0.2 # jinja2 # nbconvert # werkzeug -marshmallow==3.26.0 +marshmallow==3.26.1 # via # environs # great-expectations @@ -473,7 +473,7 @@ milvus-lite==2.4.11 # via pymilvus minio==7.2.11 # via feast (setup.py) -mistune==3.1.0 +mistune==3.1.1 # via # great-expectations # nbconvert @@ -504,7 +504,7 @@ mypy-protobuf==3.3.0 # via feast (setup.py) nbclient==0.10.2 # via nbconvert -nbconvert==7.16.5 +nbconvert==7.16.6 # via jupyter-server nbformat==5.10.4 # via @@ -551,6 +551,7 @@ packaging==24.2 # gunicorn # ibis-substrait # ipykernel + # jupyter-events # jupyter-server # jupyterlab # jupyterlab-server @@ -581,7 +582,7 @@ parsy==2.1 # via ibis-framework partd==1.4.2 # via dask -pbr==6.1.0 +pbr==6.1.1 # via mock pexpect==4.9.0 # via ipython @@ -773,7 +774,7 @@ python-json-logger==3.2.1 # via jupyter-events python-keycloak==4.2.2 # via feast (setup.py) -pytz==2024.2 +pytz==2025.1 # via # great-expectations # ibis-framework @@ -790,7 +791,7 @@ pyyaml==6.0.2 # pre-commit # responses # uvicorn -pyzmq==26.2.0 +pyzmq==26.2.1 # via # ipykernel # jupyter-client @@ -855,7 +856,7 @@ ruamel-yaml==0.17.40 # via great-expectations ruamel-yaml-clib==0.2.12 # via ruamel-yaml -ruff==0.9.3 +ruff==0.9.5 # via feast (setup.py) s3transfer==0.11.2 # via boto3 @@ -868,6 +869,7 @@ setuptools==75.8.0 # grpcio-tools # jupyterlab # kubernetes + # pbr # pip-tools # pymilvus # singlestoredb @@ -889,7 +891,7 @@ sniffio==1.3.1 # httpx snowballstemmer==2.2.0 # via sphinx -snowflake-connector-python[pandas]==3.13.0 +snowflake-connector-python[pandas]==3.13.2 # via feast (setup.py) sortedcontainers==2.4.0 # via snowflake-connector-python @@ -909,11 +911,11 @@ sphinxcontrib-qthelp==2.0.0 # via sphinx sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sqlalchemy[mypy]==2.0.37 +sqlalchemy[mypy]==2.0.38 # via feast (setup.py) sqlglot==23.12.2 # via ibis-framework -sqlite-vec==0.1.1 +sqlite-vec==0.1.6 # via feast (setup.py) sqlparams==6.2.0 # via singlestoredb @@ -985,7 +987,7 @@ traitlets==5.14.3 # nbclient # nbconvert # nbformat -trino==0.332.0 +trino==0.333.0 # via feast (setup.py) typeguard==4.4.1 # via feast (setup.py) @@ -1003,7 +1005,7 @@ types-python-dateutil==2.9.0.20241206 # via # feast (setup.py) # arrow -types-pytz==2024.2.0.20241221 +types-pytz==2025.1.0.20250204 # via feast (setup.py) types-pyyaml==6.0.12.20241230 # via feast (setup.py) @@ -1027,6 +1029,7 @@ typing-extensions==4.12.2 # azure-core # azure-identity # azure-storage-blob + # beautifulsoup4 # fastapi # great-expectations # ibis-framework diff --git a/sdk/python/requirements/py3.9-requirements.txt b/sdk/python/requirements/py3.9-requirements.txt index bdef2f69c81..1b82c994a1c 100644 --- a/sdk/python/requirements/py3.9-requirements.txt +++ b/sdk/python/requirements/py3.9-requirements.txt @@ -12,7 +12,7 @@ attrs==25.1.0 # referencing bigtree==0.23.1 # via feast (setup.py) -certifi==2024.12.14 +certifi==2025.1.31 # via requests charset-normalizer==3.4.1 # via requests @@ -35,9 +35,9 @@ dill==0.3.9 # via feast (setup.py) exceptiongroup==1.2.2 # via anyio -fastapi==0.115.7 +fastapi==0.115.8 # via feast (setup.py) -fsspec==2024.12.0 +fsspec==2025.2.0 # via dask gunicorn==23.0.0 # via @@ -67,7 +67,7 @@ markupsafe==3.0.2 # via jinja2 mmh3==5.1.0 # via feast (setup.py) -mypy==1.14.1 +mypy==1.15.0 # via sqlalchemy mypy-extensions==1.0.0 # via mypy @@ -111,7 +111,7 @@ python-dateutil==2.9.0.post0 # via pandas python-dotenv==1.0.1 # via uvicorn -pytz==2024.2 +pytz==2025.1 # via pandas pyyaml==6.0.2 # via @@ -132,7 +132,7 @@ six==1.17.0 # via python-dateutil sniffio==1.3.1 # via anyio -sqlalchemy[mypy]==2.0.37 +sqlalchemy[mypy]==2.0.38 # via feast (setup.py) starlette==0.45.3 # via fastapi diff --git a/setup.py b/setup.py index 16240ff2722..f20c94d5511 100644 --- a/setup.py +++ b/setup.py @@ -90,7 +90,7 @@ ] SQLITE_VEC_REQUIRED = [ - "sqlite-vec==v0.1.1", + "sqlite-vec==v0.1.6", ] TRINO_REQUIRED = ["trino>=0.305.0,<0.400.0", "regex"] From b16fb400fd63fdc0168cb1f845638fc003724fd4 Mon Sep 17 00:00:00 2001 From: Tommy Hughes IV Date: Fri, 7 Feb 2025 13:48:00 -0600 Subject: [PATCH 12/30] feat: Operator - make server container creation explicit in the CR (#5024) add server option Signed-off-by: Tommy Hughes --- examples/operator-quickstart/feast.yaml | 27 +- .../api/v1alpha1/featurestore_types.go | 26 +- .../api/v1alpha1/zz_generated.deepcopy.go | 23 +- .../crd/bases/feast.dev_featurestores.yaml | 1551 +++++++++-------- .../config/samples/kustomization.yaml | 2 +- ...=> v1alpha1_featurestore_all_servers.yaml} | 10 +- .../v1alpha1_featurestore_db_persistence.yaml | 13 +- ...a1_featurestore_openshift_tls_disable.yaml | 19 +- ...alpha1_featurestore_services_loglevel.yaml | 14 +- infra/feast-operator/dist/install.yaml | 1551 +++++++++-------- infra/feast-operator/docs/api/markdown/ref.md | 43 +- .../featurestore_controller_db_store_test.go | 18 +- .../featurestore_controller_ephemeral_test.go | 22 +- ...restore_controller_kubernetes_auth_test.go | 22 +- .../featurestore_controller_loglevel_test.go | 28 +- ...eaturestore_controller_objectstore_test.go | 6 +- .../featurestore_controller_oidc_auth_test.go | 22 +- .../featurestore_controller_pvc_test.go | 22 +- .../featurestore_controller_test.go | 50 +- ...featurestore_controller_test_utils_test.go | 4 +- .../featurestore_controller_tls_test.go | 10 +- .../controller/services/repo_config.go | 12 +- .../controller/services/repo_config_test.go | 13 +- .../internal/controller/services/services.go | 188 +- .../internal/controller/services/tls.go | 58 +- .../internal/controller/services/tls_test.go | 28 +- .../internal/controller/services/util.go | 18 +- .../v1alpha1_default_featurestore.yaml | 6 +- ...v1alpha1_remote_registry_featurestore.yaml | 6 +- 29 files changed, 1929 insertions(+), 1883 deletions(-) rename infra/feast-operator/config/samples/{v1alpha1_featurestore_all_services_default.yaml => v1alpha1_featurestore_all_servers.yaml} (53%) diff --git a/examples/operator-quickstart/feast.yaml b/examples/operator-quickstart/feast.yaml index def24bd9a4c..d1d7e4df867 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 19b13be8c55..845b2657271 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 cb5a4eb34ba..36f5bd33973 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 81f8ee310d2..6344896fb83 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 35eb822651a..ecb2e09c95b 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 1eef0874fff..ccaeb31db25 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 eaeca893491..bcecc33a3e4 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 2389356be71..7b9c5819646 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 1291ea7dfae..e738e6352be 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 2ef2845475e..62f8c2fe161 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 e29ad08e9e2..d9702fa6b04 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 a379c33ff14..e4f5847583e 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 06d0cd3466e..6de38263e75 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 9003fb83d52..dd799a8c8e8 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 bdd1d867319..418e57bb8e9 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 12ab5cc4d91..aed8db000e0 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 590f7335d25..f192d07cd08 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 488b0661661..bb795e8972c 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 c3512dd7837..f1259162c0f 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 e49ba3a9201..c1d0cd0f0e9 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 60d6b2224fa..883cfe940aa 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 0a5dd11544e..50ad3b92858 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 0ed0fb62e06..8a4c2a61239 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 cc7d1d215fb..a1151487b6f 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 7d8cbd16933..ae3819ab6b9 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 22102dfb7dc..eeae0de3ebc 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 fc6f57c780f..c4a8f89c672 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 9ce14113de5..3d707fbafd9 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 a8845d2963f..73f8880dc14 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: From ec6f1b750ed49ef36c5e3aa9f8db1d030bf80047 Mon Sep 17 00:00:00 2001 From: lokeshrangineni <19699092+lokeshrangineni@users.noreply.github.com> Date: Fri, 7 Feb 2025 17:18:32 -0500 Subject: [PATCH 13/30] feat: Adding volumes and volumeMounts support to Feature Store CR. (#4983) * Squashed volume and volumeMounts commits for rebase Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> * resolving master rebase conflicts. Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> * resolving master rebase conflicts. few more missing files. Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> * Modifying the sample file as per the new code changes. Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> * Modifying the sample file as per the new code changes. Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> * incorporating code review comments. Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> --------- Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> --- .../api/v1alpha1/featurestore_types.go | 14 +- .../api/v1alpha1/zz_generated.deepcopy.go | 14 + .../crd/bases/feast.dev_featurestores.yaml | 3102 +++++++++++++---- ..._featurestore_postgres_db_volumes_ssl.yaml | 85 + infra/feast-operator/dist/install.yaml | 3102 +++++++++++++---- infra/feast-operator/docs/api/markdown/ref.md | 13 +- ...tore_controller_volume_volumemount_test.go | 215 ++ .../internal/controller/services/services.go | 42 + 8 files changed, 5187 insertions(+), 1400 deletions(-) create mode 100644 infra/feast-operator/config/samples/v1alpha1_featurestore_postgres_db_volumes_ssl.yaml create mode 100644 infra/feast-operator/internal/controller/featurestore_controller_volume_volumemount_test.go diff --git a/infra/feast-operator/api/v1alpha1/featurestore_types.go b/infra/feast-operator/api/v1alpha1/featurestore_types.go index 845b2657271..c73806df3b6 100644 --- a/infra/feast-operator/api/v1alpha1/featurestore_types.go +++ b/infra/feast-operator/api/v1alpha1/featurestore_types.go @@ -81,6 +81,8 @@ type FeatureStoreServices struct { DeploymentStrategy *appsv1.DeploymentStrategy `json:"deploymentStrategy,omitempty"` // Disable the 'feast repo initialization' initContainer DisableInitContainers bool `json:"disableInitContainers,omitempty"` + // Volumes specifies the volumes to mount in the FeatureStore deployment. A corresponding `VolumeMount` should be added to whichever feast service(s) require access to said volume(s). + Volumes []corev1.Volume `json:"volumes,omitempty"` } // OfflineStore configures the deployed offline store service @@ -112,6 +114,7 @@ var ValidOfflineStoreFilePersistenceTypes = []string{ // OfflineStoreDBStorePersistence configures the DB store persistence for the offline store service type OfflineStoreDBStorePersistence struct { + // Type of the persistence type you want to use. Allowed values are: snowflake.offline, bigquery, redshift, spark, postgres, trino, redis, athena, mssql // +kubebuilder:validation:Enum=snowflake.offline;bigquery;redshift;spark;postgres;trino;redis;athena;mssql Type string `json:"type"` // Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. @@ -146,7 +149,7 @@ type OnlineStorePersistence struct { DBPersistence *OnlineStoreDBStorePersistence `json:"store,omitempty"` } -// OnlineStoreFilePersistence configures the file-based persistence for the offline store service +// OnlineStoreFilePersistence configures the file-based persistence for the online store service // +kubebuilder:validation:XValidation:rule="(!has(self.pvc) && has(self.path)) ? self.path.startsWith('/') : true",message="Ephemeral stores must have absolute paths." // +kubebuilder:validation:XValidation:rule="(has(self.pvc) && has(self.path)) ? !self.path.startsWith('/') : true",message="PVC path must be a file name only, with no slashes." // +kubebuilder:validation:XValidation:rule="has(self.path) ? !(self.path.startsWith('s3://') || self.path.startsWith('gs://')) : true",message="Online store does not support S3 or GS buckets." @@ -155,8 +158,9 @@ type OnlineStoreFilePersistence struct { PvcConfig *PvcConfig `json:"pvc,omitempty"` } -// OnlineStoreDBStorePersistence configures the DB store persistence for the offline store service +// OnlineStoreDBStorePersistence configures the DB store persistence for the online store service type OnlineStoreDBStorePersistence struct { + // Type of the persistence type you want to use. Allowed values are: snowflake.online, redis, ikv, datastore, dynamodb, bigtable, postgres, cassandra, mysql, hazelcast, singlestore, hbase, elasticsearch, qdrant, couchbase, milvus // +kubebuilder:validation:Enum=snowflake.online;redis;ikv;datastore;dynamodb;bigtable;postgres;cassandra;mysql;hazelcast;singlestore;hbase;elasticsearch;qdrant;couchbase;milvus Type string `json:"type"` // Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. @@ -211,6 +215,7 @@ type RegistryFilePersistence struct { // RegistryDBStorePersistence configures the DB store persistence for the registry service type RegistryDBStorePersistence struct { + // Type of the persistence type you want to use. Allowed values are: sql, snowflake.registry // +kubebuilder:validation:Enum=sql;snowflake.registry Type string `json:"type"` // Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. @@ -289,6 +294,11 @@ type ServerConfigs struct { // Allowed values: "debug", "info", "warning", "error", "critical". // +kubebuilder:validation:Enum=debug;info;warning;error;critical LogLevel *string `json:"logLevel,omitempty"` + // VolumeMounts defines the list of volumes that should be mounted into the feast container. + // This allows attaching persistent storage, config files, secrets, or other resources + // required by the Feast components. Ensure that each volume mount has a corresponding + // volume definition in the Volumes field. + VolumeMounts []corev1.VolumeMount `json:"volumeMounts,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 36f5bd33973..49418e5f87e 100644 --- a/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -191,6 +191,13 @@ func (in *FeatureStoreServices) DeepCopyInto(out *FeatureStoreServices) { *out = new(v1.DeploymentStrategy) (*in).DeepCopyInto(*out) } + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]corev1.Volume, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureStoreServices. @@ -739,6 +746,13 @@ func (in *ServerConfigs) DeepCopyInto(out *ServerConfigs) { *out = new(string) **out = **in } + if in.VolumeMounts != nil { + in, out := &in.VolumeMounts, &out.VolumeMounts + *out = make([]corev1.VolumeMount, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // 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 6344896fb83..7d9385df430 100644 --- a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml +++ b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml @@ -341,6 +341,28 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object type: object onlineStore: @@ -613,6 +635,28 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object type: object registry: @@ -886,6 +930,28 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object type: object remote: @@ -1084,333 +1150,860 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object - type: object - required: - - feastProject - type: object - status: - properties: - applied: - properties: - authz: - properties: - kubernetes: - properties: - roles: + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" type: string - type: array - type: object - oidc: - properties: - secretRef: - properties: - name: - default: "" + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: type: string - type: object - x-kubernetes-map-type: atomic - required: - - secretRef - type: object - type: object - x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, - c)' - feastProject: - pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ - type: string - services: - properties: - deploymentStrategy: - properties: - rollingUpdate: - properties: - maxSurge: - anyOf: - - 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: - persistence: - properties: - file: + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: properties: - pvc: + fieldRef: properties: - create: - properties: - accessModes: - items: - type: string - type: array - resources: - properties: - 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 - storageClassName: - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: + apiVersion: + type: string + fieldPath: type: string - ref: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic required: - - mountPath + - fieldPath 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('^/[^:]*$') - type: - enum: - - file - - dask - - duckdb - type: string - type: object - store: - properties: - secretKeyName: + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: type: string - secretRef: + resourceFieldRef: properties: - name: - default: "" + 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 - type: - enum: - - snowflake.offline - - bigquery - - redshift - - spark - - postgres - - trino - - redis - - athena - - mssql - type: string required: - - secretRef - - type + - path 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: + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: properties: - name: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + 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 + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: type: string - value: + volumeAttributesClassName: type: string - valueFrom: - properties: - configMapKeyRef: + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: properties: key: type: string - name: - default: "" + mode: + format: int32 + type: integer + path: type: string - optional: - type: boolean required: - key + - path 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: + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: 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: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: type: string + 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 required: - - resource + - path type: object - x-kubernetes-map-type: atomic - secretKeyRef: + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: properties: key: type: string - name: - default: "" + mode: + format: int32 + type: integer + path: type: string - optional: - type: boolean required: - key + - path 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: - 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: + type: array + x-kubernetes-list-type: atomic name: default: "" type: string + optional: + type: boolean type: object x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + required: + - feastProject + type: object + status: + properties: + applied: + properties: + authz: + properties: + kubernetes: + properties: + roles: + items: + type: string + type: array + type: object + oidc: + properties: + secretRef: + properties: + name: + default: "" + type: string type: object + x-kubernetes-map-type: atomic + required: + - secretRef type: object - onlineStore: + type: object + x-kubernetes-validations: + - message: One selection required between kubernetes or oidc. + rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + c)' + feastProject: + pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ + type: string + services: + properties: + deploymentStrategy: + properties: + rollingUpdate: + properties: + maxSurge: + anyOf: + - 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: persistence: properties: file: properties: - path: - type: string pvc: properties: create: @@ -1464,19 +2057,13 @@ spec: - message: Mount path must start with '/' and must not contain ':' rule: self.mountPath.matches('^/[^:]*$') + type: + enum: + - file + - dask + - duckdb + type: string type: object - x-kubernetes-validations: - - message: Ephemeral stores must have absolute paths. - rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') - : 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: Online store does not support S3 or GS - buckets. - rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' store: properties: secretKeyName: @@ -1490,22 +2077,15 @@ spec: x-kubernetes-map-type: atomic type: enum: - - snowflake.online + - snowflake.offline + - bigquery + - redshift + - spark + - postgres + - trino - redis - - ikv - - datastore - - dynamodb - - bigtable - - postgres - - cassandra - - mysql - - hazelcast - - singlestore - - hbase - - elasticsearch - - qdrant - - couchbase - - milvus + - athena + - mssql type: string required: - secretRef @@ -1675,481 +2255,1609 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object type: object - registry: + onlineStore: properties: - local: + persistence: properties: - persistence: + file: properties: - file: + path: + type: string + pvc: properties: - path: - type: string - pvc: + create: properties: - create: + accessModes: + items: + type: string + type: array + resources: properties: - accessModes: - items: - type: string - type: array - resources: - properties: - 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 + 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 - storageClassName: - type: string type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: + storageClassName: type: string - ref: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - 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: - 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: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: type: string - secretRef: + ref: properties: name: default: "" type: string type: object x-kubernetes-map-type: atomic - type: - enum: - - sql - - snowflake.registry - type: string required: - - secretRef - - type + - 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('^/[^:]*$') 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: + - message: Ephemeral stores must have absolute paths. + rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') + : 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: Online store does not support S3 or GS + buckets. + rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + store: properties: - env: - items: + secretKeyName: + 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)' + server: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: 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: + configMapKeyRef: properties: + key: + type: string name: default: "" type: string optional: type: boolean + required: + - key type: object x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: + 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 - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string - resources: + 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: - 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 + tlsCrt: + type: string + tlsKey: + type: string type: object - tls: + secretRef: properties: - disable: - type: boolean - secretKeyNames: + 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' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + type: object + type: object + registry: + properties: + local: + properties: + persistence: + properties: + file: + properties: + path: + type: string + pvc: properties: - tlsCrt: - type: string - tlsKey: - type: string + create: + properties: + accessModes: + items: + type: string + type: array + resources: + properties: + 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 + storageClassName: + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + type: string + ref: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + 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: + 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: + 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' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + type: object + type: object + remote: + properties: + feastRef: + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + hostname: + type: string + tls: + properties: + certName: + type: string + configMapRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - certName + - configMapRef + type: object + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, + c)' + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.local), has(self.remote)].exists_one(c, + c)' + ui: + 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: + 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' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + type: object + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + 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 + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + 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 + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + 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 + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic type: object - secretRef: + secret: properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic name: default: "" type: string + optional: + type: boolean type: object x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object 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 - remote: - properties: - feastRef: - properties: - name: - type: string - namespace: - type: string - required: - - name - type: object - hostname: - type: string - tls: - properties: - certName: - type: string - configMapRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - required: - - certName - - configMapRef - type: object - type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, - c)' - type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.local), has(self.remote)].exists_one(c, - c)' - ui: - properties: - env: - items: + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: properties: - name: + group: type: string - value: + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: 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 + - registry + - volume type: object - type: array - envFrom: - items: + rbd: properties: - configMapRef: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + type: string + readOnly: + type: boolean + secretRef: properties: name: default: "" type: string - optional: - type: boolean type: object x-kubernetes-map-type: atomic - prefix: + user: + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + type: string + gateway: type: string + protectionDomain: + type: string + readOnly: + type: boolean secretRef: properties: name: default: "" type: string - optional: - type: boolean type: object x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string - resources: - properties: - claims: + secret: + properties: + defaultMode: + format: int32 + type: integer items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: properties: name: + default: "" 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 + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array type: object required: - feastProject diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_postgres_db_volumes_ssl.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_postgres_db_volumes_ssl.yaml new file mode 100644 index 00000000000..bfef906aab8 --- /dev/null +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_postgres_db_volumes_ssl.yaml @@ -0,0 +1,85 @@ +apiVersion: v1 +kind: Secret +metadata: + name: postgres-secret + namespace: default + labels: + app: postgres +stringData: + POSTGRES_DB: mydatabase + POSTGRES_USER: admin + POSTGRES_PASSWORD: password +--- +apiVersion: v1 +kind: Secret +metadata: + name: feast-data-stores + namespace: default +stringData: + sql: | + path: postgresql+psycopg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgresql.default.svc.cluster.local:5432/${POSTGRES_DB}?sslmode=require&sslrootcert=/var/lib/postgresql/certs/ca.crt&sslcert=/var/lib/postgresql/certs/tls.crt&sslkey=/var/lib/postgresql/certs/tls.key + cache_ttl_seconds: 60 + sqlalchemy_config_kwargs: + echo: false + pool_pre_ping: true + postgres: | + host: postgresql.default.svc.cluster.local + port: 5432 + database: ${POSTGRES_DB} + db_schema: public + user: ${POSTGRES_USER} + password: ${POSTGRES_PASSWORD} + sslmode: require + sslkey_path: /var/lib/postgresql/certs/tls.key + sslcert_path: /var/lib/postgresql/certs/tls.crt + sslrootcert_path: /var/lib/postgresql/certs/ca.crt +--- +apiVersion: feast.dev/v1alpha1 +kind: FeatureStore +metadata: + name: example + namespace: default +spec: + feastProject: postgres_tls_sample + services: + volumes: + - name: postgres-certs + secret: + secretName: postgresql-client-certs + items: + - key: ca.crt + path: ca.crt + mode: 0644 # Readable by all, required by PostgreSQL + - key: tls.crt + path: tls.crt + mode: 0644 # Required for the client certificate + - key: tls.key + path: tls.key + mode: 0640 # Required for the private key + offlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + onlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-data-stores + server: + volumeMounts: + - name: postgres-certs + mountPath: /var/lib/postgresql/certs + readOnly: true + envFrom: + - secretRef: + name: postgres-secret \ No newline at end of file diff --git a/infra/feast-operator/dist/install.yaml b/infra/feast-operator/dist/install.yaml index 62f8c2fe161..a57848769c5 100644 --- a/infra/feast-operator/dist/install.yaml +++ b/infra/feast-operator/dist/install.yaml @@ -349,6 +349,28 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object type: object onlineStore: @@ -621,6 +643,28 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object type: object registry: @@ -894,6 +938,28 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object type: object remote: @@ -1092,333 +1158,860 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object - type: object - required: - - feastProject - type: object - status: - properties: - applied: - properties: - authz: - properties: - kubernetes: - properties: - roles: + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" type: string - type: array - type: object - oidc: - properties: - secretRef: - properties: - name: - default: "" + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: type: string - type: object - x-kubernetes-map-type: atomic - required: - - secretRef - type: object - type: object - x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, - c)' - feastProject: - pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ - type: string - services: - properties: - deploymentStrategy: - properties: - rollingUpdate: - properties: - maxSurge: - anyOf: - - 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: - persistence: - properties: - file: + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: properties: - pvc: + fieldRef: properties: - create: - properties: - accessModes: - items: - type: string - type: array - resources: - properties: - 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 - storageClassName: - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: + apiVersion: + type: string + fieldPath: type: string - ref: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic required: - - mountPath + - fieldPath 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('^/[^:]*$') - type: - enum: - - file - - dask - - duckdb - type: string - type: object - store: - properties: - secretKeyName: + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: type: string - secretRef: + resourceFieldRef: properties: - name: - default: "" + 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 - type: - enum: - - snowflake.offline - - bigquery - - redshift - - spark - - postgres - - trino - - redis - - athena - - mssql - type: string required: - - secretRef - - type + - path 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: + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: properties: - name: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + 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 + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: type: string - value: + volumeAttributesClassName: type: string - valueFrom: - properties: - configMapKeyRef: + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: properties: key: type: string - name: - default: "" + mode: + format: int32 + type: integer + path: type: string - optional: - type: boolean required: - key + - path 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: + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: 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: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: type: string + 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 required: - - resource + - path type: object - x-kubernetes-map-type: atomic - secretKeyRef: + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: properties: key: type: string - name: - default: "" + mode: + format: int32 + type: integer + path: type: string - optional: - type: boolean required: - key + - path 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: - 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: + type: array + x-kubernetes-list-type: atomic name: default: "" type: string + optional: + type: boolean type: object x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + required: + - feastProject + type: object + status: + properties: + applied: + properties: + authz: + properties: + kubernetes: + properties: + roles: + items: + type: string + type: array + type: object + oidc: + properties: + secretRef: + properties: + name: + default: "" + type: string type: object + x-kubernetes-map-type: atomic + required: + - secretRef type: object - onlineStore: + type: object + x-kubernetes-validations: + - message: One selection required between kubernetes or oidc. + rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + c)' + feastProject: + pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ + type: string + services: + properties: + deploymentStrategy: + properties: + rollingUpdate: + properties: + maxSurge: + anyOf: + - 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: persistence: properties: file: properties: - path: - type: string pvc: properties: create: @@ -1472,19 +2065,13 @@ spec: - message: Mount path must start with '/' and must not contain ':' rule: self.mountPath.matches('^/[^:]*$') + type: + enum: + - file + - dask + - duckdb + type: string type: object - x-kubernetes-validations: - - message: Ephemeral stores must have absolute paths. - rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') - : 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: Online store does not support S3 or GS - buckets. - rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' store: properties: secretKeyName: @@ -1498,22 +2085,15 @@ spec: x-kubernetes-map-type: atomic type: enum: - - snowflake.online + - snowflake.offline + - bigquery + - redshift + - spark + - postgres + - trino - redis - - ikv - - datastore - - dynamodb - - bigtable - - postgres - - cassandra - - mysql - - hazelcast - - singlestore - - hbase - - elasticsearch - - qdrant - - couchbase - - milvus + - athena + - mssql type: string required: - secretRef @@ -1683,481 +2263,1609 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array type: object type: object - registry: + onlineStore: properties: - local: + persistence: properties: - persistence: + file: properties: - file: + path: + type: string + pvc: properties: - path: - type: string - pvc: + create: properties: - create: + accessModes: + items: + type: string + type: array + resources: properties: - accessModes: - items: - type: string - type: array - resources: - properties: - 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 + 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 - storageClassName: - type: string type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: + storageClassName: type: string - ref: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - 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: - 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: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: type: string - secretRef: + ref: properties: name: default: "" type: string type: object x-kubernetes-map-type: atomic - type: - enum: - - sql - - snowflake.registry - type: string required: - - secretRef - - type + - 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('^/[^:]*$') 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: + - message: Ephemeral stores must have absolute paths. + rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') + : 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: Online store does not support S3 or GS + buckets. + rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + store: properties: - env: - items: + secretKeyName: + 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)' + server: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: 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: + configMapKeyRef: properties: + key: + type: string name: default: "" type: string optional: type: boolean + required: + - key type: object x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: + 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 - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string - resources: + 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: - 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 + tlsCrt: + type: string + tlsKey: + type: string type: object - tls: + secretRef: properties: - disable: - type: boolean - secretKeyNames: + 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' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + type: object + type: object + registry: + properties: + local: + properties: + persistence: + properties: + file: + properties: + path: + type: string + pvc: properties: - tlsCrt: - type: string - tlsKey: - type: string + create: + properties: + accessModes: + items: + type: string + type: array + resources: + properties: + 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 + storageClassName: + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + type: string + ref: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + 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: + 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: + 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' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + type: object + type: object + remote: + properties: + feastRef: + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + hostname: + type: string + tls: + properties: + certName: + type: string + configMapRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - certName + - configMapRef + type: object + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, + c)' + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.local), has(self.remote)].exists_one(c, + c)' + ui: + 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: + 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' + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + type: object + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + 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 + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + 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 + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + 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 + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic type: object - secretRef: + secret: properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic name: default: "" type: string + optional: + type: boolean type: object x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object 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 - remote: - properties: - feastRef: - properties: - name: - type: string - namespace: - type: string - required: - - name - type: object - hostname: - type: string - tls: - properties: - certName: - type: string - configMapRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - required: - - certName - - configMapRef - type: object - type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, - c)' - type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.local), has(self.remote)].exists_one(c, - c)' - ui: - properties: - env: - items: + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: properties: - name: + group: type: string - value: + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: 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 + - registry + - volume type: object - type: array - envFrom: - items: + rbd: properties: - configMapRef: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + type: string + readOnly: + type: boolean + secretRef: properties: name: default: "" type: string - optional: - type: boolean type: object x-kubernetes-map-type: atomic - prefix: + user: + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + type: string + gateway: type: string + protectionDomain: + type: string + readOnly: + type: boolean secretRef: properties: name: default: "" type: string - optional: - type: boolean type: object x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string - resources: - properties: - claims: + secret: + properties: + defaultMode: + format: int32 + type: integer items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: properties: name: + default: "" 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 + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array type: object required: - feastProject diff --git a/infra/feast-operator/docs/api/markdown/ref.md b/infra/feast-operator/docs/api/markdown/ref.md index d9702fa6b04..820d9b90539 100644 --- a/infra/feast-operator/docs/api/markdown/ref.md +++ b/infra/feast-operator/docs/api/markdown/ref.md @@ -110,6 +110,7 @@ _Appears in:_ | `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 | +| `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#volume-v1-core) array_ | Volumes specifies the volumes to mount in the FeatureStore deployment. A corresponding `VolumeMount` should be added to whichever feast service(s) require access to said volume(s). | #### FeatureStoreSpec @@ -209,7 +210,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `type` _string_ | | +| `type` _string_ | Type of the persistence type you want to use. Allowed values are: snowflake.offline, bigquery, redshift, spark, postgres, trino, redis, athena, mssql | | `secretRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. | | `secretKeyName` _string_ | By default, the selected store "type" is used as the SecretKeyName | @@ -278,14 +279,14 @@ _Appears in:_ -OnlineStoreDBStorePersistence configures the DB store persistence for the offline store service +OnlineStoreDBStorePersistence configures the DB store persistence for the online store service _Appears in:_ - [OnlineStorePersistence](#onlinestorepersistence) | Field | Description | | --- | --- | -| `type` _string_ | | +| `type` _string_ | Type of the persistence type you want to use. Allowed values are: snowflake.online, redis, ikv, datastore, dynamodb, bigtable, postgres, cassandra, mysql, hazelcast, singlestore, hbase, elasticsearch, qdrant, couchbase, milvus | | `secretRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. | | `secretKeyName` _string_ | By default, the selected store "type" is used as the SecretKeyName | @@ -294,7 +295,7 @@ _Appears in:_ -OnlineStoreFilePersistence configures the file-based persistence for the offline store service +OnlineStoreFilePersistence configures the file-based persistence for the online store service _Appears in:_ - [OnlineStorePersistence](#onlinestorepersistence) @@ -459,6 +460,10 @@ _Appears in:_ | `tls` _[TlsConfigs](#tlsconfigs)_ | | | `logLevel` _string_ | LogLevel sets the logging level for the server Allowed values: "debug", "info", "warning", "error", "critical". | +| `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#volumemount-v1-core) array_ | VolumeMounts defines the list of volumes that should be mounted into the feast container. +This allows attaching persistent storage, config files, secrets, or other resources +required by the Feast components. Ensure that each volume mount has a corresponding +volume definition in the Volumes field. | #### ServiceHostnames diff --git a/infra/feast-operator/internal/controller/featurestore_controller_volume_volumemount_test.go b/infra/feast-operator/internal/controller/featurestore_controller_volume_volumemount_test.go new file mode 100644 index 00000000000..521f18cdc36 --- /dev/null +++ b/infra/feast-operator/internal/controller/featurestore_controller_volume_volumemount_test.go @@ -0,0 +1,215 @@ +/* +Copyright 2024 Feast Community. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controller + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/feast-dev/feast/infra/feast-operator/internal/controller/handler" + "github.com/feast-dev/feast/infra/feast-operator/internal/controller/services" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + feastdevv1alpha1 "github.com/feast-dev/feast/infra/feast-operator/api/v1alpha1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("FeatureStore Controller - Deployment Volumes and VolumeMounts", func() { + Context("When deploying featureStore Spec we should have an option do Volumes and VolumeMounts", func() { + const resourceName = "services-ephemeral" + const offlineType = "duckdb" + var pullPolicy = corev1.PullAlways + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + Namespace: "default", + } + featurestore := &feastdevv1alpha1.FeatureStore{} + onlineStorePath := "/data/online.db" + registryPath := "/data/registry.db" + + BeforeEach(func() { + By("creating the custom resource for the Kind FeatureStore") + err := k8sClient.Get(ctx, typeNamespacedName, featurestore) + if err != nil && errors.IsNotFound(err) { + resource := createFeatureStoreVolumeResource(resourceName, image, pullPolicy) + resource.Spec.Services.OfflineStore.Persistence = &feastdevv1alpha1.OfflineStorePersistence{ + FilePersistence: &feastdevv1alpha1.OfflineStoreFilePersistence{ + Type: offlineType, + }, + } + resource.Spec.Services.OnlineStore.Persistence = &feastdevv1alpha1.OnlineStorePersistence{ + FilePersistence: &feastdevv1alpha1.OnlineStoreFilePersistence{ + Path: onlineStorePath, + }, + } + resource.Spec.Services.Registry = &feastdevv1alpha1.Registry{ + Local: &feastdevv1alpha1.LocalRegistryConfig{ + Persistence: &feastdevv1alpha1.RegistryPersistence{ + FilePersistence: &feastdevv1alpha1.RegistryFilePersistence{ + Path: registryPath, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, resource)).To(Succeed()) + } + }) + AfterEach(func() { + resource := &feastdevv1alpha1.FeatureStore{} + err := k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance FeatureStore") + Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) + + }) + + It("should successfully reconcile the resource and volumes and volumeMounts should be available", func() { + By("Reconciling the created resource") + controllerReconciler := &FeatureStoreReconciler{ + Client: k8sClient, + Scheme: k8sClient.Scheme(), + } + + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + + resource := &feastdevv1alpha1.FeatureStore{} + err = k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + feast := services.FeastServices{ + Handler: handler.FeastHandler{ + Client: controllerReconciler.Client, + Context: ctx, + Scheme: controllerReconciler.Scheme, + FeatureStore: resource, + }, + } + + deploy := &appsv1.Deployment{} + objMeta := feast.GetObjectMeta() + err = k8sClient.Get(ctx, types.NamespacedName{ + Name: objMeta.Name, + Namespace: objMeta.Namespace, + }, deploy) + + Expect(err).NotTo(HaveOccurred()) + + // Extract the PodSpec from DeploymentSpec + podSpec := deploy.Spec.Template.Spec + + // Validate Volumes + // Validate Volumes - Check if our test volume exists among multiple + Expect(podSpec.Volumes).To(ContainElement(WithTransform(func(v corev1.Volume) string { + return v.Name + }, Equal("test-volume"))), "Expected volume 'test-volume' to be present") + + // Ensure 'online' container has the test volume mount + var onlineContainer *corev1.Container + for i, container := range podSpec.Containers { + if container.Name == "online" { + onlineContainer = &podSpec.Containers[i] + break + } + } + Expect(onlineContainer).ToNot(BeNil(), "Expected to find container 'online'") + + // Validate that 'online' container has the test-volume mount + Expect(onlineContainer.VolumeMounts).To(ContainElement(WithTransform(func(vm corev1.VolumeMount) string { + return vm.Name + }, Equal("test-volume"))), "Expected 'online' container to have volume mount 'test-volume'") + + // Ensure all other containers do NOT have the test volume mount + for _, container := range podSpec.Containers { + if container.Name != "online" { + Expect(container.VolumeMounts).ToNot(ContainElement(WithTransform(func(vm corev1.VolumeMount) string { + return vm.Name + }, Equal("test-volume"))), "Unexpected volume mount 'test-volume' found in container "+container.Name) + } + } + + }) + }) +}) + +func createFeatureStoreVolumeResource(resourceName string, image string, pullPolicy corev1.PullPolicy) *feastdevv1alpha1.FeatureStore { + volume := corev1.Volume{ + Name: "test-volume", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + } + volumeMount := corev1.VolumeMount{ + Name: "test-volume", + MountPath: "/data", + } + + return &feastdevv1alpha1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Namespace: "default", + }, + Spec: feastdevv1alpha1.FeatureStoreSpec{ + FeastProject: feastProject, + Services: &feastdevv1alpha1.FeatureStoreServices{ + Volumes: []corev1.Volume{volume}, + OfflineStore: &feastdevv1alpha1.OfflineStore{ + Server: &feastdevv1alpha1.ServerConfigs{ + ContainerConfigs: feastdevv1alpha1.ContainerConfigs{}, + }, + }, + OnlineStore: &feastdevv1alpha1.OnlineStore{ + Server: &feastdevv1alpha1.ServerConfigs{ + VolumeMounts: []corev1.VolumeMount{volumeMount}, + ContainerConfigs: feastdevv1alpha1.ContainerConfigs{ + DefaultCtrConfigs: feastdevv1alpha1.DefaultCtrConfigs{ + Image: &image, + }, + OptionalCtrConfigs: feastdevv1alpha1.OptionalCtrConfigs{ + ImagePullPolicy: &pullPolicy, + Resources: &corev1.ResourceRequirements{}, + }, + }, + }, + }, + UI: &feastdevv1alpha1.ServerConfigs{ + ContainerConfigs: feastdevv1alpha1.ContainerConfigs{ + DefaultCtrConfigs: feastdevv1alpha1.DefaultCtrConfigs{ + Image: &image, + }, + OptionalCtrConfigs: feastdevv1alpha1.OptionalCtrConfigs{ + ImagePullPolicy: &pullPolicy, + Resources: &corev1.ResourceRequirements{}, + }, + }, + }, + }, + }, + } +} diff --git a/infra/feast-operator/internal/controller/services/services.go b/infra/feast-operator/internal/controller/services/services.go index a1151487b6f..ece43074599 100644 --- a/infra/feast-operator/internal/controller/services/services.go +++ b/infra/feast-operator/internal/controller/services/services.go @@ -355,6 +355,7 @@ func (feast *FeastServices) setPod(podSpec *corev1.PodSpec) error { feast.mountTlsConfigs(podSpec) feast.mountPvcConfigs(podSpec) feast.mountEmptyDirVolumes(podSpec) + feast.mountUserDefinedVolumes(podSpec) return nil } @@ -420,10 +421,51 @@ func (feast *FeastServices) setContainer(containers *[]corev1.Container, feastTy }, } applyOptionalCtrConfigs(container, serverConfigs.ContainerConfigs.OptionalCtrConfigs) + volumeMounts := feast.getVolumeMounts(feastType) + if len(volumeMounts) > 0 { + container.VolumeMounts = append(container.VolumeMounts, volumeMounts...) + } *containers = append(*containers, *container) } } +func (feast *FeastServices) mountUserDefinedVolumes(podSpec *corev1.PodSpec) { + var volumes []corev1.Volume + if feast.Handler.FeatureStore.Spec.Services != nil { + volumes = feast.Handler.FeatureStore.Spec.Services.Volumes + } + if len(volumes) > 0 { + podSpec.Volumes = append(podSpec.Volumes, volumes...) + } +} + +func (feast *FeastServices) getVolumeMounts(feastType FeastServiceType) (volumeMounts []corev1.VolumeMount) { + appliedServices := feast.Handler.FeatureStore.Status.Applied.Services + if appliedServices == nil { + return []corev1.VolumeMount{} // Return an empty slice to avoid nil issues + } + + switch feastType { + case OfflineFeastType: + if feast.isOfflineServer() { + return appliedServices.OfflineStore.Server.VolumeMounts + } + case OnlineFeastType: + if feast.isOnlineServer() { + return appliedServices.OnlineStore.Server.VolumeMounts + } + case RegistryFeastType: + if feast.isRegistryServer() { + return appliedServices.Registry.Local.Server.VolumeMounts + } + case UIFeastType: + if feast.isUiServer() { + return appliedServices.UI.VolumeMounts + } + } + return []corev1.VolumeMount{} // Default empty slice +} + func (feast *FeastServices) setRoute(route *routev1.Route, feastType FeastServiceType) error { svcName := feast.GetFeastServiceName(feastType) From 3bb0dca1692fb7087e967a9fc33a4b08720b13d2 Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Sat, 8 Feb 2025 01:11:36 -0500 Subject: [PATCH 14/30] fix: Validate entities when running get_online_features (#5031) --- sdk/python/feast/utils.py | 53 +++++++---- .../online_store/test_online_retrieval.py | 15 ++++ .../tests/unit/test_unit_feature_store.py | 88 ++++++++++++++++++- 3 files changed, 137 insertions(+), 19 deletions(-) diff --git a/sdk/python/feast/utils.py b/sdk/python/feast/utils.py index ff60217f32d..86cb08ec932 100644 --- a/sdk/python/feast/utils.py +++ b/sdk/python/feast/utils.py @@ -687,25 +687,48 @@ def _get_unique_entities( entity_name_to_join_key_map, join_key_values, ) + # Validate that all expected join keys exist and have non-empty values. + expected_keys = set(entity_name_to_join_key_map.values()) + expected_keys.discard("__dummy_id") + missing_keys = sorted( + list(set([key for key in expected_keys if key not in table_entity_values])) + ) + empty_keys = sorted( + list(set([key for key in expected_keys if not table_entity_values.get(key)])) + ) - # Convert back to rowise. - keys = table_entity_values.keys() - # Sort the rowise data to allow for grouping but keep original index. This lambda is - # sufficient as Entity types cannot be complex (ie. lists). + if missing_keys or empty_keys: + if not any(table_entity_values.values()): + raise KeyError( + f"Missing join key values for keys: {missing_keys}. " + f"No values provided for keys: {empty_keys}. " + f"Provided join_key_values: {list(join_key_values.keys())}" + ) + + # Convert the column-oriented table_entity_values into row-wise data. + keys = list(table_entity_values.keys()) + # Each row is a tuple of ValueProto objects corresponding to the join keys. rowise = list(enumerate(zip(*table_entity_values.values()))) + + # If there are no rows, return empty tuples. + if not rowise: + return (), () + + # Sort rowise so that rows with the same join key values are adjacent. rowise.sort(key=lambda row: tuple(getattr(x, x.WhichOneof("val")) for x in row[1])) - # Identify unique entities and the indexes at which they occur. - unique_entities: Tuple[Dict[str, ValueProto], ...] - indexes: Tuple[List[int], ...] - unique_entities, indexes = tuple( - zip( - *[ - (dict(zip(keys, k)), [_[0] for _ in g]) - for k, g in itertools.groupby(rowise, key=lambda x: x[1]) - ] - ) - ) + # Group rows by their composite join key value. + groups = [ + (dict(zip(keys, key_tuple)), [idx for idx, _ in group]) + for key_tuple, group in itertools.groupby(rowise, key=lambda row: row[1]) + ] + + # If no groups were formed (should not happen for valid input), return empty tuples. + if not groups: + return (), () + + # Unpack the unique entities and their original row indexes. + unique_entities, indexes = tuple(zip(*groups)) return unique_entities, indexes diff --git a/sdk/python/tests/unit/online_store/test_online_retrieval.py b/sdk/python/tests/unit/online_store/test_online_retrieval.py index 6b0adb62630..9d6b7f3d178 100644 --- a/sdk/python/tests/unit/online_store/test_online_retrieval.py +++ b/sdk/python/tests/unit/online_store/test_online_retrieval.py @@ -137,6 +137,21 @@ def test_get_online_features() -> None: assert "trips" in result + with pytest.raises(KeyError) as excinfo: + _ = store.get_online_features( + features=["driver_locations:lon"], + entity_rows=[{"customer_id": 0}], + full_feature_names=False, + ).to_dict() + + error_message = str(excinfo.value) + assert "Missing join key values for keys:" in error_message + assert ( + "Missing join key values for keys: ['customer_id', 'driver_id', 'item_id']." + in error_message + ) + assert "Provided join_key_values: ['customer_id']" in error_message + result = store.get_online_features( features=["customer_profile_pandas_odfv:on_demand_age"], entity_rows=[{"driver_id": 1, "customer_id": "5"}], diff --git a/sdk/python/tests/unit/test_unit_feature_store.py b/sdk/python/tests/unit/test_unit_feature_store.py index 19a133564f2..8d7b32760a4 100644 --- a/sdk/python/tests/unit/test_unit_feature_store.py +++ b/sdk/python/tests/unit/test_unit_feature_store.py @@ -1,6 +1,8 @@ from dataclasses import dataclass from typing import Dict, List +import pytest + from feast import utils from feast.protos.feast.types.Value_pb2 import Value @@ -17,7 +19,7 @@ class MockFeatureView: projection: MockFeatureViewProjection -def test_get_unique_entities(): +def test_get_unique_entities_success(): entity_values = { "entity_1": [Value(int64_val=1), Value(int64_val=2), Value(int64_val=1)], "entity_2": [ @@ -41,9 +43,87 @@ def test_get_unique_entities(): join_key_values=entity_values, entity_name_to_join_key_map=entity_name_to_join_key_map, ) - - assert unique_entities == ( + expected_entities = ( {"entity_1": Value(int64_val=1), "entity_2": Value(string_val="1")}, {"entity_1": Value(int64_val=2), "entity_2": Value(string_val="2")}, ) - assert indexes == ([0, 2], [1]) + expected_indexes = ([0, 2], [1]) + + assert unique_entities == expected_entities + assert indexes == expected_indexes + + +def test_get_unique_entities_missing_join_key_success(): + """ + Tests that _get_unique_entities raises a KeyError when a required join key is missing. + """ + # Here, we omit the required key for "entity_1" + entity_values = { + "entity_2": [ + Value(string_val="1"), + Value(string_val="2"), + Value(string_val="1"), + ], + } + + entity_name_to_join_key_map = {"entity_1": "entity_1", "entity_2": "entity_2"} + + fv = MockFeatureView( + name="fv_1", + entities=["entity_1", "entity_2"], + projection=MockFeatureViewProjection(join_key_map={}), + ) + + unique_entities, indexes = utils._get_unique_entities( + table=fv, + join_key_values=entity_values, + entity_name_to_join_key_map=entity_name_to_join_key_map, + ) + expected_entities = ( + {"entity_2": Value(string_val="1")}, + {"entity_2": Value(string_val="2")}, + ) + expected_indexes = ([0, 2], [1]) + + assert unique_entities == expected_entities + assert indexes == expected_indexes + # We're not say anything about the entity_1 missing from the unique_entities list + assert "entity_1" not in [entity.keys() for entity in unique_entities] + + +def test_get_unique_entities_missing_all_join_keys_error(): + """ + Tests that _get_unique_entities raises a KeyError when all required join keys are missing. + """ + entity_values_not_in_feature_view = { + "entity_3": [Value(string_val="3")], + } + entity_name_to_join_key_map = { + "entity_1": "entity_1", + "entity_2": "entity_2", + "entity_3": "entity_3", + } + + fv = MockFeatureView( + name="fv_1", + entities=["entity_1", "entity_2"], + projection=MockFeatureViewProjection(join_key_map={}), + ) + + with pytest.raises(KeyError) as excinfo: + utils._get_unique_entities( + table=fv, + join_key_values=entity_values_not_in_feature_view, + entity_name_to_join_key_map=entity_name_to_join_key_map, + ) + + error_message = str(excinfo.value) + assert ( + "Missing join key values for keys: ['entity_1', 'entity_2', 'entity_3']" + in error_message + ) + assert ( + "No values provided for keys: ['entity_1', 'entity_2', 'entity_3']" + in error_message + ) + assert "Provided join_key_values: ['entity_3']" in error_message From efbffa4be0f38166ff35f133a9b69bcbd243debd Mon Sep 17 00:00:00 2001 From: nanshakov Date: Sun, 9 Feb 2025 15:30:13 +0300 Subject: [PATCH 15/30] fix: Resolve module on windows (#4827) --- sdk/python/feast/repo_operations.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/python/feast/repo_operations.py b/sdk/python/feast/repo_operations.py index 4db0bbc6fdb..a3bf52fb10e 100644 --- a/sdk/python/feast/repo_operations.py +++ b/sdk/python/feast/repo_operations.py @@ -43,6 +43,7 @@ def py_path_to_module(path: Path) -> str: str(path.relative_to(os.getcwd()))[: -len(".py")] .replace("./", "") .replace("/", ".") + .replace("\\", ".") ) From 48a4285b3a91bd6e490d6562591de612b96a5e02 Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Sun, 9 Feb 2025 12:09:09 -0500 Subject: [PATCH 16/30] docs: Adding blog posts from feast.dev website (#5034) --- docs/SUMMARY.md | 1 + docs/blog/README.md | 21 +++ docs/blog/a-state-of-feast.md | 80 +++++++++ docs/blog/announcing-feast-0-11.md | 65 +++++++ ...faster-feature-transformations-in-feast.md | 50 ++++++ docs/blog/feast-0-10-announcement.md | 163 ++++++++++++++++++ ...vers-and-feature-views-without-entities.md | 45 +++++ ...st-0-14-adds-aws-lambda-feature-servers.md | 56 ++++++ ...ake-support-and-data-quality-monitoring.md | 37 ++++ ...-20-adds-api-and-connector-improvements.md | 41 +++++ docs/blog/feast-benchmarks.md | 65 +++++++ ...-joins-the-linux-foundation-for-ai-data.md | 37 ++++ ...2-adds-aws-redshift-and-dynamodb-stores.md | 46 +++++ docs/blog/feast-supports-vector-database.md | 43 +++++ docs/blog/go-feature-server-benchmarks.md | 55 ++++++ ...how-danny-chiao-is-keeping-feast-simple.md | 31 ++++ ...kubeflow-and-feast-with-david-aronchick.md | 31 ++++ ...ime-fraud-prediction-using-feast-on-gcp.md | 50 ++++++ ...t-for-python-based-feast-feature-server.md | 61 +++++++ docs/blog/rbac-role-based-access-controls.md | 71 ++++++++ ...g-feature-engineering-with-denormalized.md | 135 +++++++++++++++ docs/blog/the-future-of-feast.md | 38 ++++ docs/blog/the-road-to-feast-1-0.md | 35 ++++ docs/blog/what-is-a-feature-store.md | 85 +++++++++ 24 files changed, 1342 insertions(+) create mode 100644 docs/blog/README.md create mode 100644 docs/blog/a-state-of-feast.md create mode 100644 docs/blog/announcing-feast-0-11.md create mode 100644 docs/blog/faster-feature-transformations-in-feast.md create mode 100644 docs/blog/feast-0-10-announcement.md create mode 100644 docs/blog/feast-0-13-adds-on-demand-transforms-feature-servers-and-feature-views-without-entities.md create mode 100644 docs/blog/feast-0-14-adds-aws-lambda-feature-servers.md create mode 100644 docs/blog/feast-0-18-adds-snowflake-support-and-data-quality-monitoring.md create mode 100644 docs/blog/feast-0-20-adds-api-and-connector-improvements.md create mode 100644 docs/blog/feast-benchmarks.md create mode 100644 docs/blog/feast-joins-the-linux-foundation-for-ai-data.md create mode 100644 docs/blog/feast-release-0-12-adds-aws-redshift-and-dynamodb-stores.md create mode 100644 docs/blog/feast-supports-vector-database.md create mode 100644 docs/blog/go-feature-server-benchmarks.md create mode 100644 docs/blog/how-danny-chiao-is-keeping-feast-simple.md create mode 100644 docs/blog/kubeflow-and-feast-with-david-aronchick.md create mode 100644 docs/blog/machine-learning-data-stack-for-real-time-fraud-prediction-using-feast-on-gcp.md create mode 100644 docs/blog/performance-test-for-python-based-feast-feature-server.md create mode 100644 docs/blog/rbac-role-based-access-controls.md create mode 100644 docs/blog/streaming-feature-engineering-with-denormalized.md create mode 100644 docs/blog/the-future-of-feast.md create mode 100644 docs/blog/the-road-to-feast-1-0.md create mode 100644 docs/blog/what-is-a-feature-store.md diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index bbda7773b45..127b27463ec 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,6 +1,7 @@ # Table of contents * [Introduction](README.md) +* [Blog](blog/README.md) * [Community & getting help](community.md) * [Roadmap](roadmap.md) * [Changelog](https://github.com/feast-dev/feast/blob/master/CHANGELOG.md) diff --git a/docs/blog/README.md b/docs/blog/README.md new file mode 100644 index 00000000000..cc42cfe442f --- /dev/null +++ b/docs/blog/README.md @@ -0,0 +1,21 @@ +# Blog Posts + +Welcome to the Feast blog! Here you'll find articles about feature store development, new features, and community updates. + +## Featured Posts + +{% content-ref url="what-is-a-feature-store.md" %} +[what-is-a-feature-store.md](what-is-a-feature-store.md) +{% endcontent-ref %} + +{% content-ref url="the-future-of-feast.md" %} +[the-future-of-feast.md](the-future-of-feast.md) +{% endcontent-ref %} + +{% content-ref url="feast-supports-vector-database.md" %} +[feast-supports-vector-database.md](feast-supports-vector-database.md) +{% endcontent-ref %} + +{% content-ref url="rbac-role-based-access-controls.md" %} +[rbac-role-based-access-controls.md](rbac-role-based-access-controls.md) +{% endcontent-ref %} diff --git a/docs/blog/a-state-of-feast.md b/docs/blog/a-state-of-feast.md new file mode 100644 index 00000000000..7343effdcb4 --- /dev/null +++ b/docs/blog/a-state-of-feast.md @@ -0,0 +1,80 @@ +# A State of Feast + +*January 21, 2021* | *Willem Pienaar* + +## Introduction + +Two years ago we first announced the launch of Feast, an open source feature store for machine learning. Feast is an operational data system that solves some of the key challenges that ML teams encounter while productionizing machine learning systems. + +Recognizing that ML and Feast have advanced since we launched, we take a moment today to discuss the past, present and future of Feast. We consider the more significant lessons we learned while building Feast, where we see the project heading, and why teams should consider adopting Feast as part of their operational ML stacks. + +## Background + +Feast was developed to address the challenges faced while productionizing data for machine learning. In our original [Google Cloud article](https://cloud.google.com/blog/products/ai-machine-learning/introducing-feast-an-open-source-feature-store-for-machine-learning), we highlighted some of these challenges, namely: + +1. Features aren't reused. +2. Feature definitions are inconsistent across teams. +3. Getting features into production is hard. +4. Feature values are inconsistent between training and serving. + +Whereas an industry to solve data transformations and data-quality problems already existed, our focus for shaping Feast was to overcome operational ML hurdles that exist between data science and ML engineering. Toward that end, our initial aim was to provide: + +1. Registry: The registry is a common catalog with which to explore, develop, collaborate on, and publish new feature definitions within and across teams. It is the central interface for all interactions with the feature store. +2. Ingestion: A means for continually ingesting batch and streaming data and storing consistent copies in both an offline and online store. This layer automates most data-management work and ensures that features are always available for serving. +3. Serving: A feature-retrieval interface which provides a temporally consistent view of features for both training and online serving. Serving improves iteration speed by minimizing coupling to data infrastructure, and prevents training-serving skew through consistent data access. + +Guided by this design, we co-developed and shipped Feast with our friends over at Google. We then open sourced the project in early 2019, and have since been running Feast in production and at scale. In our follow up blog post, [Bridging ML Models and Data](https://blog.gojekengineering.com/feast-bridging-ml-models-and-data), we touched on the impact Feast has had at companies like Gojek. + +## Feast today + +Teams, large and small, are increasingly searching for ways to simplify the productionization and maintenance of their ML systems at scale. Since open sourcing Feast, we've seen both the demand for these tools and the activity around this project soar. Working alongside our open source community, we've released key pieces of our stack throughout the last year, and steadily expanded Feast into a robust feature store. Highlights include: + +* Point-in-time correct queries that prevent feature data leakage. +* A query optimized table-based data model in the form of feature sets. +* Storage connectors with implementations for Cassandra and Redis Cluster. +* Statistics generation and data validation through TFDV integration. +* Authentication and authorization support for SDKs and APIs. +* Diagnostic tooling through request/response logging, audit logs, and Statsd integration. + +Feast has grown more rapidly than initially anticipated, with multiple large companies, including Agoda, Gojek, Farfetch, Postmates, and Zulily adopting and/or contributing to the project. We've also been working closely with other open source teams, and we are excited to share that Feast is now a [component in Kubeflow](https://www.kubeflow.org/docs/components/feature-store/). Over the coming months we will be enhancing this integration, making it easier for users to deploy Feast and Kubeflow together. + +## Lessons learned + +Through frequent engagement with our community and by way of running Feast in production ourselves, we've learned critical lessons: + +Feast requires too much infrastructure: Requiring users provision a large system is a big ask. A minimal Feast deployment requires Kafka, Zookeeper, Postgres, Redis, and multiple Feast services. + +Feast lacks composability: Requiring all infrastructural components be present in order to have a functional system removes all modularity. + +Ingestion is too complex: Incorporating a Kafka-based stream-first ingestion layer trivializes data consistency across stores, but the complete ingestion flow from source to sink can still mysteriously fail at multiple points. + +Our technology choices hinder generalization: Leveraging technologies like BigQuery, Apache Beam on Dataflow, and Apache Kafka has allowed us to move faster in delivering functionality. However, these technologies now impede our ability to generalize to other clouds or deployment environments. + +## The future of Feast + +> *"Always in motion is the future."* +> – Yoda, The Empire Strikes Back + +While feature stores have already become essential systems at large technology companies, we believe their widespread adoption will begin in 2021. We also foresee the release of multiple managed feature stores over the next year, as vendors seek to enter the burgeoning operational ML market. + +As we've discussed, feature stores serve both offline and production ML needs, and therefore are primarily built by engineers for engineers. What we need, however, is a feature store that's purpose-built for data-science workflows. Feast will move away from an infrastructure-centric approach toward a more localized experience that does just this: builds on teams' existing data-science workflows. + +The lessons we've learned during the preceding two years have crystallized a vision for what Feast should become: a light-weight modular feature store. One that's easy to pick up, adds value to teams large and small, and can be progressively applied to production use cases that span multiple teams, projects, and cloud-environments. We aim to reach this by applying the following design principles: + +1. Python-first: First-class support for running a minimal version of Feast entirely from a notebook, with all infrastructural dependencies becoming optional enhancements. + * Encourages quick evaluation of the software and ensures Feast is user friendly + * Minimizes the operational burden of running the system in production + * Simplifies testing, developing, and maintaining Feast + +## Next Steps + +Our vision for Feast is not only ambitious, but actionable. Our next release, Feast 0.8, is the product of collaborating with both our open source community and our friends over at [Tecton](https://tecton.ai/). + +1. Python-first: We are migrating all core logic to Python, starting with training dataset retrieval and job management, providing a more responsive development experience. +2. Modular ingestion: We are shifting to managing batch and streaming ingestion separately, leading to more actionable metrics, logs, and statistics and an easier to understand and operate system. +3. Support for AWS: We are replacing GCP-specific technologies like Beam on Dataflow with Spark and adding native support for running Feast on AWS, our first steps toward cloud-agnosticism. +4. Data-source integrations: We are introducing support for a host of new data sources (Kinesis, Kafka, S3, GCS, BigQuery) and data formats (Parquet, JSON, Avro), ensuring teams can seamlessly integrate Feast into their existing data-infrastructure. + +## Get involved + +We've been inspired by the soaring community interest in and contributions to Feast. If you're curious to learn more about our mission to build a best-in-class feature store, or are looking to build your own: Check out our resources, say hello, and get involved! diff --git a/docs/blog/announcing-feast-0-11.md b/docs/blog/announcing-feast-0-11.md new file mode 100644 index 00000000000..b3b1f2f4aca --- /dev/null +++ b/docs/blog/announcing-feast-0-11.md @@ -0,0 +1,65 @@ +# Announcing Feast 0.11 + +*June 23, 2021* | *Jay Parthasarthy & Willem Pienaar* + +Feast 0.11 is here! This is the first release after the major changes introduced in Feast 0.10. We've focused on two areas in particular: + +1. Introducing a new online store, Redis, which supports feature serving at high throughput and low latency. +2. Improving the Feast user experience through reduced boilerplate, smoother workflows, and improved error messages. A key addition here is the introduction of *feature inferencing,* which allows Feast to dynamically discover data schemas in your source data. + +Let's get into it! + +### Support for Redis as an online store 🗝 + +Feast 0.11 introduces support for Redis as an online store, allowing teams to easily scale up Feast to support high volumes of online traffic. Using Redis with Feast is as easy as adding a few lines of configuration to your feature_store.yaml file: + +```yaml +project: fraud +registry: data/registry.db +provider: local +online_store: + type: redis + connection_string: localhost:6379 +``` + +Feast is then able to read and write from Redis as its online store. + +```bash +$ feast materialize + +Materializing 3 feature views to 2021-06-15 18:43:03+00:00 into the redis online store. + +user_account_features from 2020-06-16 18:43:04 to 2021-06-15 18:43:13: +100%|███████████████████████| 9944/9944 [00:04<00:00, 20065.15it/s] +user_transaction_count_7d from 2021-06-08 18:43:21 to 2021-06-15 18:43:03: +100%|███████████████████████| 9674/9674 [00:04<00:00, 19943.82it/s] +``` + +We're also working on making it easier for teams to add their own storage and compute systems through plugin interfaces. Please see this RFC for more details on the proposal. + +### Feature Inferencing 🔎 + +Before 0.11, users had to define each feature individually when defining Feature Views. Now, Feast infers the schema of a Feature View based on upstream data sources, significantly reducing boilerplate. + +Before: +```python +driver_hourly_stats_view = FeatureView( + name="driver_hourly_stats", + entities=["driver_id"], + ttl=timedelta(days=1), + features=[ + Feature(name="conv_rate", dtype=ValueType.FLOAT), + ], + input=BigQuerySource(table_ref="feast-oss.demo_data.driver_hourly_stats"), +) +``` + +Aside from these additions, a wide variety of small bug fixes, and UX improvements made it into this release. [Check out the changelog](https://github.com/feast-dev/feast/blob/master/CHANGELOG.md) for a full list of what's new. + +Special thanks and a big shoutout to the community contributors whose changes made it into this release: [MattDelac](https://github.com/MattDelac), [mavysavydav](https://github.com/mavysavydav), [szalai1](https://github.com/szalai1), [rightx2](https://github.com/rightx2) + +### Help us design Feast for AWS 🗺️ + +The 0.12 release will include native support for AWS. We are looking to meet with teams that are considering using Feast to gather feedback and help shape the product as design partners. We often help our design partners out with architecture or design reviews. If this sounds helpful to you, [join us in Slack](http://slack.feastsite.wpenginepowered.com/), or [book a call with Feast maintainers here](https://calendly.com/d/gc29-y88c/feast-chat-w-willem). + +### Feast from around the web 📣 diff --git a/docs/blog/faster-feature-transformations-in-feast.md b/docs/blog/faster-feature-transformations-in-feast.md new file mode 100644 index 00000000000..689a5b84abd --- /dev/null +++ b/docs/blog/faster-feature-transformations-in-feast.md @@ -0,0 +1,50 @@ +# Faster Feature Transformations in Feast 🏎️💨 + +*December 5, 2024* | *Francisco Javier Arceo, Shuchu Han* + +*Thank you to [Shuchu Han](https://www.linkedin.com/in/shuchu/), [Ross Briden](https://www.linkedin.com/in/ross-briden/), [Ankit Nadig](https://www.linkedin.com/in/ankit-nadig/), and the folks at Affirm for inspiring this work and creating an initial proof of concept.* + +Feature engineering is at the core of building high-performance machine learning models. The Feast team has introduced two major enhancements to [On Demand Feature Views](https://docs.feast.dev/reference/beta-on-demand-feature-views) (ODFVs), pushing the boundaries of efficiency and flexibility for data scientists and engineers. Here's a closer look at these exciting updates: + +## 1. Transformations with Native Python + +Traditionally, transformations in ODFVs were limited to Pandas-based operations. While powerful, Pandas transformations can be computationally expensive for certain use cases. Feast now introduces Native Python Mode, a feature that allows users to write transformations using pure Python. + +Key benefits of Native Python Mode include: + +* Blazing Speed: Transformations using Native Python are nearly 10x faster compared to Pandas for many operations. +* Intuitive Design: This mode supports list-based and singleton (row-level) transformations, making it easier for data scientists to think in terms of individual rows rather than entire datasets. +* Versatility: Users can now switch between batch and singleton transformations effortlessly, catering to both historical and online retrieval scenarios. + +Using the cProfile library and snakeviz we were able to profile the runtime for the ODFV transformation using both Pandas and Native python and observed a nearly 10x reduction in speed. + +## 2. Transformations on Writes + +Until now, ODFVs operated solely as transformations on reads, applying logic during online feature retrieval. While this ensured flexibility, it sometimes came at the cost of increased latency during retrieval. Feast now supports transformations on writes, enabling users to apply transformations during data ingestion and store the transformed features in the online store. + +Why does this matter? + +* Reduced Online Latency: With transformations pre-applied at ingestion, online retrieval becomes a straightforward lookup, significantly improving performance for latency-sensitive applications. +* Operational Flexibility: By toggling the write_to_online_store parameter, users can choose whether transformations should occur at write time (to optimize reads) or at read time (to preserve data freshness). + +Here's an example of applying transformations during ingestion: + +```python +@on_demand_feature_view( + sources=[driver_hourly_stats_view], +) + +df = pd.DataFrame() +df["conv_rate_adjusted"] = features_df["conv_rate"] * 1.1 +return df +``` + +With this new capability, data engineers can optimize online retrieval performance without sacrificing the flexibility of on-demand transformations. + +### The Future of ODFVs and Feature Transformations + +These enhancements bring ODFVs closer to the goal of seamless feature engineering at scale. By combining high-speed Python-based transformations with the ability to optimize retrieval latency, Feast empowers teams to build more efficient, responsive, and production-ready feature pipelines. + +For more detailed examples and use cases, check out the [documentation for On Demand Feature Views](https://docs.feast.dev/reference/beta-on-demand-feature-views). Whether you're a data scientist prototyping features or an engineer optimizing a production system, the new ODFV capabilities offer the tools you need to succeed. + +The future of Feature Transformations in Feast will be to unify feature transformations and feature views to allow for a simpler API. If you have thoughts or interest in giving feedback to the maintainers, feel free to comment directly on [the GitHub Issue](https://github.com/feast-dev/feast/issues/4584) or in [the RFC](https://docs.google.com/document/d/1KXCXcsXq1bU...). diff --git a/docs/blog/feast-0-10-announcement.md b/docs/blog/feast-0-10-announcement.md new file mode 100644 index 00000000000..54b10880d14 --- /dev/null +++ b/docs/blog/feast-0-10-announcement.md @@ -0,0 +1,163 @@ +# Announcing Feast 0.10 + +*April 15, 2021* | *Jay Parthasarthy & Willem Pienaar* + +Today, we're announcing Feast 0.10, an important milestone towards our vision for a lightweight feature store. Feast is an open source feature store that helps you serve features in production. It prevents feature leakage by building training datasets from your batch data, automates the process of loading and serving features in an online feature store, and ensures your models in production have a consistent view of feature data. + +With Feast 0.10, we've dramatically simplified the process of managing a feature store. This new release allows you to: + +* Run a minimal local feature store from your notebook +* Deploy a production-ready feature store into a cloud environment in 30 seconds +* Operate a feature store without Kubernetes, Spark, or self-managed infrastructure + +We think Feast 0.10 is the simplest and fastest way to productionize features. Let's get into it! + +## The challenge with feature stores + +In our previous post, [A State of Feast](https://blog.feastsite.wpenginepowered.com/post), we shared our vision for building a feature store that is accessible to all ML teams. Since then, we've been working towards this vision by shipping support for AWS, Azure, and on-prem deployments. + +Over the last couple of months we've seen a surge of interest in Feast. ML teams are increasingly being tasked with building production ML systems, and many are looking for an open source tool to help them operationalize their feature data in a structured way. However, many of these teams still can't afford to run their own feature stores: + +> "Feature stores are big infrastructure!" + +The conventional wisdom is that feature stores should be built and operated as platforms. It's not surprising why many have this notion. Feature stores require access to compute layers, offline and online databases, and need to directly interface with production systems. + +This infrastructure-centric approach means that operating your own feature store is a daunting task. Many teams simply don't have the resources to deploy and manage a feature store. Instead, ML teams are being forced to hack together their own custom scripts or end up delaying their projects as they wait for engineering support. + +## Towards a simpler feature store + +Our vision for Feast is to provide a feature store that a single data scientist can deploy for a single ML project, but can also scale up for use by large platform teams. We've made all infrastructure optional in Feast 0.10. That means no Spark, no Kubernetes, and no APIs, unless you need them. If you're just starting out we won't ask you to deploy and manage a platform. + +Additionally, we've pulled out the core of our software into a single Python framework. This framework allows teams to define features and declaratively provision a feature store based on those definitions, to either local or cloud environments. If you're just starting out with feature stores, you'll only need to manage a Git repository and run the Feast CLI or SDK, nothing more. + +Feast 0.10 introduces a first-class local mode: not installed through Docker containers, but through pip. It allows users to start a minimal feature store entirely from a notebook, allowing for rapid development against sample data and for testing against the same ML frameworks they're using in production. Finally, we've also begun adding first-class support for managed services. Feast 0.10 ships with native support for GCP, with more providers on the way. Platform teams running Feast at scale get the best of both worlds: a feature store that is able to scale up to production workloads by leveraging serverless technologies, with the flexibility to deploy the complete system to Kubernetes if needed. + +## The new experience + +Machine learning teams today are increasingly being tasked with building models that serve predictions online. These teams are also sitting on a wealth of feature data in warehouses like BigQuery, Snowflake, and Redshift. It's natural to use these features for model training, but hard to serve these features online at low latency. + +## 1. Create a feature repository + +Installing Feast is now as simple as: +```bash +pip install feast +``` + +We'll scaffold a feature repository based on a GCP template: +```bash +feast init driver_features -t gcp +``` + +A feature repository consists of a *feature_store.yaml*, and a collection of feature definitions. +``` +driver_features/ +└── feature_store.yaml +└── driver_features.py +``` + +The *feature_store.yaml* file contains infrastructural configuration necessary to set up a feature store. The *project* field is used to uniquely identify a feature store, the *registry* is a source of truth for feature definitions, and the *provider* specifies the environment in which our feature store will run. + +feature_store.yaml: +```yaml +project: driver_features +registry: gs://driver-fs/ +provider: gcp +``` + +The feature repository also contains Python based feature definitions, like *driver_features.py*. This file contains a single entity and a single feature view. Together they describe a collection of features in BigQuery that can be used for model training or serving. + +## 2. Set up a feature store + +Next we run *apply* to set up our feature store on GCP. +```bash +feast apply +``` + +Running Feast apply will register our feature definitions with the GCS feature registry and prepare our infrastructure for writing and reading features. Apply can be run idempotently, and is meant to be executed from CI when feature definitions change. + +At this point we haven't moved any data. We've only stored our feature definition metadata in the object store registry (GCS) and Feast has configured our infrastructure (Firestore in this case). + +## 3. Build a training dataset + +Feast is able to build training datasets from our existing feature data, including data at rest in our upstream tables in BigQuery. Now that we've registered our feature definitions with Feast we are able to build a training dataset. + +From our training pipeline: +```python +# Connect to the feature registry +fs = FeatureStore( + RepoConfig( + registry="gs://driver-fs/", + project="driver_features" + ) +) + +# Load our driver events table. This dataframe will be enriched with features from BigQuery +driver_events = pd.read_csv("driver_events.csv") + +# Build a training dataset from features in BigQuery +training_df = fs.get_historical_features( + feature_refs=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate" + ], + entity_df=driver_events +).to_df() + +# Train a model, and ship it into production +model = ml.fit(training_data) +``` + +The code snippet above will join the user provided dataframe driver_events to our driver_stats BigQuery table in a point-in-time correct way. Feast is able to use the temporal properties (event timestamps) of feature tables to reconstruct a view of features at a specific point in time, from any amount of feature tables or views. + +## 4. Load features into the online store + +At this point we have trained our model and we are ready to serve it. However, our online feature store contains no data. In order to load features into the feature store we run *materialize-incremental* from the command line. + +Feast provides materialization commands that load features from an offline store into an online store. The default GCP provider exports features from BigQuery and writes them directly into Firestore using an in-memory process. Teams running at scale may want to leverage cloud-based ingestion by using a different provider configuration. + +## 5. Read features at low latency + +Now that our online store has been populated with the latest feature data, it's possible for our ML model services to read online features for prediction. + +From our model serving service: +```python +# Connect to the feature store +fs = feast.FeatureStore( + RepoConfig(registry="gs://driver-fs/", project="driver_features") +) + +# Query Firestore for online feature values +online_features = fs.get_online_features( + feature_refs=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate" + ], + entity_rows=[{"driver_id": 1001}, {"driver_id": 1002}], +).to_dict() + +# Make a prediction +model.predict(online_features) +``` + +## 6. That's it + +At this point, you can schedule a Feast materialization job and set up our CI pipelines to update our infrastructure as feature definitions change. + +## What's next + +Our vision for Feast is to build a simple yet scalable feature store. With 0.10, we've shipped local workflows, infrastructure pluggability, and removed all infrastructural overhead. But we're still just beginning this journey, and there's still lots of work left to do. + +Over the next few months we will focus on making Feast as accessible to teams as possible. This means adding support for more data sources, streams, and cloud providers, but also means working closely with our users in unlocking new operational ML use cases and integrations. + +Feast is a community driven project, which means extensibility is always a key focus area for us. We want to make it super simple for you to add new data stores, compute layers, or bring Feast to a new stack. We've already seen teams begin development towards community providers for 0.10 during pre-release, and we welcome community contributions in this area. + +The next few months are going to be big ones for the Feast project. Stay tuned for more news, and we'd love for you to get started using Feast 0.10 today! + +## Get started + +* ✨ Try out our [quickstart](https://docs.feastsite.wpenginepowered.com/quickstart) if you're new to Feast, or learn more about Feast through our [documentation](https://docs.feastsite.wpenginepowered.com). +* 👋 Join our [Slack](http://slack.feastsite.wpenginepowered.com/) and say hello! Slack is the best forum for you to get in touch with Feast maintainers, and we love hearing feedback from teams trying out 0.10 Feast. +* 📢 Register for [apply()](https://www.applyconf.com/) – the ML data engineering conference, where we'll [demo Feast 0.10](https://www.applyconf.com/agenda/rethinking-feature-stores) and discuss [future developments for AWS](https://www.applyconf.com/agenda/bringing-feast-to-aws). +* 🔥 For teams that want to continue to run Feast on Kubernetes with Spark, have a look at our installation guides and Helm charts. + +🛠️ Thinking about contributing to Feast? Check out our [code on GitHub](https://github.com/feast-dev/feast)! diff --git a/docs/blog/feast-0-13-adds-on-demand-transforms-feature-servers-and-feature-views-without-entities.md b/docs/blog/feast-0-13-adds-on-demand-transforms-feature-servers-and-feature-views-without-entities.md new file mode 100644 index 00000000000..63dd71a52b6 --- /dev/null +++ b/docs/blog/feast-0-13-adds-on-demand-transforms-feature-servers-and-feature-views-without-entities.md @@ -0,0 +1,45 @@ +# Feast 0.13 adds on-demand transforms, feature servers, and feature views without entities + +*October 2, 2021* | *Danny Chiao, Tsotne Tabidze, Achal Shah, and Felix Wang* + +We are delighted to announce the release of [Feast 0.13](https://github.com/feast-dev/feast/releases/tag/v0.13.0), which introduces: + +* [Experimental] On demand feature views, which allow for consistently applied transformations in both training and online paths. This also introduces the concept of request data, which is data only available at the time of the prediction request, as potential inputs into these transformations +* [Experimental] Python feature servers, which allow you to quickly deploy a local HTTP server to serve online features. Serverless deployments and java feature servers to come soon! +* Feature views without entities, which allow you to specify features that should only be joined on event timestamps. You do not need lists of entities / entity values when defining and retrieving features from these feature views. + +Experimental features are subject to API changes in the near future as we collect feedback. If you have thoughts, please don't hesitate to reach out to the Feast team! + +### [Experimental] On demand feature views + +On demand feature views allows users to use existing features and request data to transform and create new features. Users define Python transformation logic which is executed in both historical retrieval and online retrieval paths.‌ This unlocks many use cases including fraud detection and recommender systems, and reduces training / serving skew by allowing for consistently applied transformations. Example features may include: + +* Transactional features such as `transaction_amount_greater_than_7d_average` where the inputs to features are part of the transaction, booking, or order event. +* Features requiring the current location or time such as `user_account_age`, `distance_driver_customer` +* Feature crosses where the keyspace is too large to precompute such as `movie_category_x_movie_rating` or `lat_bucket_x_lon_bucket` + +Currently, these transformations are executed locally. Future milestones include building a feature transformation server for executing transformations at higher scale. + +First, we define the transformations: + +```python +# Define a request data source which encodes features / information only +# available at request time (e.g. part of the user initiated HTTP request) +input_request = RequestDataSource( + name="vals_to_add", + schema={ + "val_to_add": ValueType.INT64, + } +) +``` + +See [On demand feature view](https://docs.feastsite.wpenginepowered.com/reference/on-demand-feature-view) for detailed info on how to use this functionality. + +### [Experimental] Python feature server + +The Python feature server provides an HTTP endpoint that serves features from the feature store. This enables users to retrieve features from Feast using any programming language that can make HTTP requests. As of now, it's only possible to run the server locally. A remote serverless feature server is currently being developed. Additionally, a low latency java feature server is in development. + +```bash +$ feast init feature_repo +Creating a new Feast repository in /home/tsotne/feast/feature_repo. +``` diff --git a/docs/blog/feast-0-14-adds-aws-lambda-feature-servers.md b/docs/blog/feast-0-14-adds-aws-lambda-feature-servers.md new file mode 100644 index 00000000000..45062d2d54e --- /dev/null +++ b/docs/blog/feast-0-14-adds-aws-lambda-feature-servers.md @@ -0,0 +1,56 @@ +# Feast 0.14 adds AWS Lambda feature servers + +*October 23, 2021* | *Tsotne Tabidze, Felix Wang* + +We are delighted to announce the release of [Feast 0.14](https://github.com/feast-dev/feast/releases/tag/v0.14.0), which introduces a new feature and several important improvements: + +* [Experimental] AWS Lambda feature servers, which allow you to quickly deploy an HTTP server to serve online features on AWS Lambda. GCP Cloud Run and Java feature servers are coming soon! +* Bug fixes around performance. The core online serving path is now significantly faster. +* Improvements for developer experience. The integration tests are now faster, and temporary tables created during integration tests are immediately dropped after the test. + +Experimental features are subject to API changes in the near future as we collect feedback. If you have thoughts, please don't hesitate to reach out to the Feast team! + +### [Experimental] AWS Lambda feature servers + +Prior to Feast 0.13, the only way for users to retrieve online features was to use the Python SDK. This was restrictive, so Feast 0.13 introduced local Python feature servers, allowing users to deploy a local HTTP server to serve their online features. Feast 0.14 now allows users to deploy a feature server on AWS Lambda to quickly serve features at scale. The new AWS Lambda feature servers are available for feature stores using the AWS provider. + +To deploy a feature server to AWS Lambda, they must be enabled and be given the appropriate permissions: + +```yaml +project: dev +registry: s3://feast/registries/dev +provider: aws +online_store: + region: us-west-2 +offline_store: + cluster_id: feast + region: us-west-2 + user: admin + database: feast + s3_staging_location: s3://feast/redshift/tests/staging_location + iam_role: arn:aws:iam::{aws_account}:role/redshift_s3_access_role +flags: + alpha_features: true + aws_lambda_feature_server: true +feature_server: + enabled: True + execution_role_name: arn:aws:iam::{aws_account}:role/lambda_execution_role +``` + +Calling `feast apply` will then deploy the feature server. The precise endpoint can be determined with by calling `feast endpoint`, and the endpoint can then be queried as follows: + +See [AWS Lambda feature server](https://docs.feastsite.wpenginepowered.com/reference/feature-servers/aws-lambda) for detailed info on how to use this functionality. + +### Performance bug fixes and developer experience improvements + +The provider for a feature store is now cached instead of being instantiated repeatedly, making the core online serving path 30% faster. + +Integration tests now run significantly faster on Github Actions due to caching. Also, tables created during integration tests were previously not always cleaned up properly; now they are always deleted immediately after the integration tests finish. + +### What's next + +We are collaborating with the community on supporting streaming sources, low latency serving, a Python feature transformation server for on demand transforms, improved support for Kubernetes deployments, and more. + +In addition, there is active community work on building Hive, Snowflake, Azure, Astra, Presto, and Alibaba Cloud connectors. If you have thoughts on what to build next in Feast, please fill out this [form](https://docs.google.com/forms/d/e/1FAIpQLSfa1nR). + +Download Feast 0.14 today from [PyPI](https://pypi.org/project/feast/) (or pip install feast) and try it out! Let us know on our [slack channel](http://slack.feastsite.wpenginepowered.com/). diff --git a/docs/blog/feast-0-18-adds-snowflake-support-and-data-quality-monitoring.md b/docs/blog/feast-0-18-adds-snowflake-support-and-data-quality-monitoring.md new file mode 100644 index 00000000000..4b4321e3259 --- /dev/null +++ b/docs/blog/feast-0-18-adds-snowflake-support-and-data-quality-monitoring.md @@ -0,0 +1,37 @@ +# Feast 0.18 adds Snowflake support and data quality monitoring + +*February 14, 2022* | *Felix Wang* + +We are delighted to announce the release of Feast [0.18](https://github.com/feast-dev/feast/releases/tag/v0.18.0), which introduces several new features and other improvements: + +* Snowflake offline store, which allows you to define and use features stored in Snowflake. +* [Experimental] Saved Datasets, which allow training datasets to be persisted in an offline store. +* [Experimental] Data quality monitoring, which allows you to validate your training data with Great Expectations. Future work will allow you to detect issues with upstream data pipelines and check for training-serving skew. +* Python feature server graduation from alpha status. +* Performance improvements to on demand feature views, protobuf serialization and deserialization, and the Python feature server. + +Experimental features are subject to API changes in the near future as we collect feedback. If you have thoughts, please don't hesitate to reach out to the Feast team through our [Slack](http://slack.feastsite.wpenginepowered.com/)! + +### Snowflake offline store + +Prior to Feast 0.18, Feast had first-class support for Google BigQuery and AWS Redshift as offline stores. In addition, there were various plugins for Snowflake, Azure, Postgres, and Hive. Feast 0.18 introduces first-class support for Snowflake as an offline store, so users can more easily leverage features defined in Snowflake. The Snowflake offline store can be used with the AWS, GCP, and Azure providers. + +### [Experimental] Saved Datasets + +Training datasets generated via `get_historical_features` can now be persisted in an offline store and reused later. This functionality will be primarily needed to generate reference datasets for validation purposes (see next section) but also could be useful in other use cases like caching results of a computationally intensive point-in-time join. + +### [Experimental] Data quality monitoring + +Feast 0.18 includes the first milestone of our data quality monitoring work. Many users have requested ways to validate their training and serving data, as well as monitor for training-serving skew. Feast 0.18 allows users to validate their training data through an integration with [Great Expectations](https://greatexpectations.io/). Users can declare one of the previously generated training datasets as a reference for this validation by persisting it as a "saved dataset" (see previous section). More details about future milestones of data quality monitoring can be found [here](https://docs.feastsite.wpenginepowered.com/v/master/reference/data-quality). There's also a [tutorial on validating historical features](https://docs.feastsite.wpenginepowered.com/v/master/how-to-guides/validation/validating-historical-features) that demonstrates all new concepts in action. + +### Performance improvements + +The Feast team and community members have made several significant performance improvements. For example, the Python feature server performance was improved by switching to a more efficient serving interface. Improving our protobuf serialization and deserialization logic led to speedups in on demand feature views. The Datastore implementation was also sped up by batching operations. For more details, please see our [blog post](https://feastsite.wpenginepowered.com/blog/feast-benchmarks/) with detailed benchmarks! + +### What's next + +We are collaborating with the community on the first milestone of the `feast plan` command, future milestones of data quality monitoring, and a consolidation of our online serving logic into Golang. + +In addition, there is active community work on adding support for Snowflake as an online store, merging the Azure plugin into the main Feast repo, and more. If you have thoughts on what to build next in Feast, please fill out this [form](https://docs.google.com/forms/d/e/1FAIpQLSfa1nR). + +Download Feast 0.18 today from [PyPI](https://pypi.org/project/feast/) diff --git a/docs/blog/feast-0-20-adds-api-and-connector-improvements.md b/docs/blog/feast-0-20-adds-api-and-connector-improvements.md new file mode 100644 index 00000000000..a15482b6344 --- /dev/null +++ b/docs/blog/feast-0-20-adds-api-and-connector-improvements.md @@ -0,0 +1,41 @@ +# Feast 0.20 adds API and connector improvements + +*April 21, 2022* | *Danny Chiao* + +We are delighted to announce the release of Feast 0.20, which introduces many new features and enhancements: + +* Many connector improvements and bug fixes (DynamoDB, Snowflake, Spark, Trino) + * Note: Trino has been officially bundled into Feast. You can now run this with `pip install "feast[trino]"`! +* Feast API changes +* [Experimental] Feast UI as an importable npm module +* [Experimental] Python SDK with embedded Go mode + +### Connector optimizations & bug fixes + +Key changes: + +* DynamoDB online store implementation is now much more efficient with batch feature retrieval (thanks [@TremaMiguel](https://github.com/TremaMiguel)!). As per updates on the [benchmark blog post](https://feastsite.wpenginepowered.com/blog/feast-benchmarks/), DynamoDB now is much more performant at high batch sizes for online feature retrieval! +* Snowflake offline store connector supports key pair authentication. +* Contrib plugins (documentation still pending, but see [old docs](https://github.com/Shopify/feast-trino)) + +### Feast API simplification + +In planning for upcoming functionality (data quality monitoring, batch + stream transformations), certain parts of the Feast API are changing. As part of this change, Feast 0.20 addresses API inconsistencies. No existing feature repos will be broken, and we intend to provide a migration script to help upgrade to the latest syntax. + +Key changes: + +* Naming changes (e.g. `FeatureView` changes from features -> schema) +* All Feast objects will be defined with keyword args (in practice not impacting users unless they use positional args) +* Key Feast object metadata will be consistently exposed through constructors (e.g. owner, description, name) +* [Experimental] Pushing transformed features (e.g. from a stream) directly to the online store: + * Favoring push sources + +### [Experimental] Feast Web UI + +See [https://github.com/feast-dev/feast/tree/master/ui](https://github.com/feast-dev/feast/tree/master/ui) to check out the new Feast Web UI! You can generate registry dumps via the Feast CLI and stand up the server at a local endpoint. You can also embed the UI as a React component and add custom tabs. + +### What's next + +In response to survey results (fill out this [form](https://forms.gle/9SpCeJnq3MayAqHe6) to give your input), the Feast community will be diving much more deeply into data quality monitoring, batch + stream transformations, and more performant / scalable materialization. + +The community is also actively involved in many efforts. Join [#feast-web-ui](https://tectonfeast.slack.com/channels/feast-web-ui) to get involved with helping on the Feast Web UI. diff --git a/docs/blog/feast-benchmarks.md b/docs/blog/feast-benchmarks.md new file mode 100644 index 00000000000..49cd0624ed4 --- /dev/null +++ b/docs/blog/feast-benchmarks.md @@ -0,0 +1,65 @@ +# Serving features in milliseconds with Feast feature store + +*February 1, 2022* | *Tsotne Tabidze, Oleksii Moskalenko, Danny Chiao* + +Feature stores are operational ML systems that serve data to models in production. The speed at which a feature store can serve features can have an impact on the performance of a model and user experience. In this blog post, we show how fast Feast is at serving features in production and describe considerations for deploying Feast. + +## Updates +Apr 19: Updated DynamoDB benchmarks for Feast 0.20 given batch retrieval improvements + +## Background + +One of the most common questions Feast users ask in our [community Slack](http://slack.feastsite.wpenginepowered.com/) is: how scalable / performant is Feast? (spoiler alert: Feast is *very* fast, serving features at <1.5ms @p99 when using Redis in the below benchmarks) + +In a survey conducted last year ([results](https://docs.google.com/forms/d/e/1FAIpQLScV2RX)), we saw that most users were tackling challenging problems like recommender systems (e.g. recommending items to buy) and fraud detection, and had strict latency requirements. + +Over 80% of survey respondents needed features to be read at less than 100ms (@p99). Taking into account that most users in this survey were supporting recommender systems, which often require ranking 100s-1000s of entities simultaneously, this becomes even more strict. Feature serving latency scales with batch size because of the need to query features for random entities and other sources of tail latency. + +In this blog, we present results from a benchmark suite ([RFC](https://docs.google.com/document/d/12UuvTQnTTCJ)), describe the benchmark setup, and provide recommendations for how to deploy Feast to meet different operational goals. + +## Considerations when deploying Feast + +There are a couple of decisions users need to make when deploying Feast to support online inference. There are two key decisions when it comes to performance: + +1. How to deploy a feature server +2. Choice of online store + +Each approach comes with different tradeoffs in terms of performance, scalability, flexibility, and ease of use. This post aims to help users decide between these approaches and enable users to easily set up their own benchmarks to see if Feast meets their own latency requirements. + +### How to deploy a feature server + +While all users setup a Feast feature repo in the same way (using the Python SDK to define and materialize features), users retrieve features from Feast in a few different ways (see also [Running Feast in Production](https://docs.feastsite.wpenginepowered.com/how-to-guides/running-feast-in-production)): + +1. Deploy a Java gRPC feature server (Beta) +2. Deploy a Python HTTP feature server +3. Deploy a serverless Python HTTP feature server on AWS Lambda +4. Use the Python client SDK to directly fetch features +5. (Advanced) Build a custom client (e.g in Go or Java) to directly read the registry and read from an online store + +The first four above come for free with Feast, while the fifth requires custom work. All options communicate with the same Feast registry component (managed by feast apply) to understand where features are stored. + +Deploying a feature server service (compared to using a Feast client that directly communicates with online stores) can enable many improvements such as better caching (e.g. across clients), improved data access management, rate limiting, centralized monitoring, supporting client libraries across multiple languages, etc. However, this comes at the cost of increased architectural complexity. Serverless architectures are on the other end of the spectrum, enabling simple deployments at the cost of latency overhead. + +### Choice of online stores + +Feast is highly pluggable and extensible and supports serving features from a range of online stores (e.g. Amazon DynamoDB, Google Cloud Datastore, Redis, PostgreSQL). Many users build their own plugins to support their specific needs / online stores. [Building a Feature Store](https://www.tecton.ai/blog/how-to-build-a-feature-store/) dives into some of the trade-offs between online stores. Easier to manage solutions like DynamoDB or Datastore often lose against Redis in terms of read performance and cost. Each store also has its own API idiosyncrasies that can impact performance. The Feast community is continuously optimizing store-specific performance. + +## Benchmark Results + +The raw data exists at [https://github.com/feast-dev/feast-benchmarks](https://github.com/feast-dev/feast-benchmarks). We choose a subset of comparisons here to answer some of the most common questions we hear from the community. + +### Summary + +* The Java feature server is very fast (e.g. p99 latency is ~1.3 ms for a single row fetch of 250 features) + * Note: The Java feature server is in Beta and does not support new functionality such as the more scalable SQL registry. + +The Beta Feast Java feature server with Redis provides very low latency retrieval (p99 < 1.5ms for single row retrieval of 250 features), but at increased architectural complexity, less first class support for functionality (e.g. no SQL registry support), and more overhead in managing Redis clusters. Using a Python server with other managed online stores like DynamoDB or Datastore is easier to manage. + +Note: there are managed services for Redis like Redis Enterprise Cloud which remove the additional complexity associated with managing Redis clusters and provide additional benefits. + +### What's next + +The community is always improving Feast performance, and we'll post updates to performance improvements in the future. Future improvements in the works include: + +* Improved on demand transformation performance +* Improved pooling of clients (e.g. we've seen that caching Google clients significantly improves response times and reduces memory consumption) diff --git a/docs/blog/feast-joins-the-linux-foundation-for-ai-data.md b/docs/blog/feast-joins-the-linux-foundation-for-ai-data.md new file mode 100644 index 00000000000..19af5632b8a --- /dev/null +++ b/docs/blog/feast-joins-the-linux-foundation-for-ai-data.md @@ -0,0 +1,37 @@ +# Feast Joins The Linux Foundation for AI & Data + +*January 22, 2021* | *Christina Harter* + +([Original post](https://lfaidata.foundation/blog/2020/11/10/feast-joins-lf-ai-data-as-new-incubation-project/)) + +LF AI & Data Foundation—the organization building an ecosystem to sustain open source innovation in artificial intelligence (AI), machine learning (ML), deep learning (DL), and Data open source projects—today is announcing FEAST as its latest Incubation Project. [Feast](https://feastsite.wpenginepowered.com/) (Feature Store) is an open source feature store for machine learning. + +Today, teams running operational machine learning systems are faced with many technical and organizational challenges: + +1. Models don't have a consistent view of feature data and are tightly coupled to data infrastructure. +2. Deploying new features in production is difficult. +3. Feature leakage decreases model accuracy. +4. Features aren't reused across projects. +5. Operational teams can't monitor the quality of data served to models. + +Developed collaboratively between [Gojek](https://www.gojek.com/) and [Google Cloud](https://cloud.google.com/) in 2018, Feast was open sourced in early 2019. The project sets out to address these challenges as follows: + +1. Providing a single data access layer that decouples models from the infrastructure used to generate, store, and serve feature data. +2. Decoupling the creation of features from the consumption of features through a centralized store, thereby allowing teams to ship features into production with minimal engineering support. +3. Providing point-in-time correct retrieval of feature data for both model training and online serving. +4. Encouraging reuse of features by allowing organizations to build a shared foundation of features. +5. Providing data-centric operational monitoring that ensures operational teams can run production machine learning systems confidently at scale. + +"Feast was created to address the data challenges we faced at Gojek while scaling machine learning for ride-hailing, food delivery, digital payments, fraud detection, and a myriad of other use cases" said Willem Pienaar, creator of Feast. "After open sourcing the project we've seen an explosion of demand for the software, leading to strong adoption and community growth. Entering the LF AI & Data Foundation is an important step for us toward decentralized governance and wider industry adoption and development." + +Jeremy Lewi, Kubeflow founder, said "Feast entering the LF AI & Data Foundation is both a major milestone for the project and recognition of the strides the project has made toward solving some of the hardest problems in productionizing data for machine learning. Technologies like Feast have the potential to shape the machine learning stack of the future, and with its incubation in LF AI & Data, the project now has the ideal environment to expand its community in building a best-in-class open source feature store." + +Dr. Ibrahim Haddad, Executive Director of LF AI & Data, said: "We are very excited to welcome FEAST to LF AI & Data and help it thrive in a vendor-neutral environment under an open governance model. With the addition of FEAST, we are increasing the number of hosted projects under the Data category and look forward to tighter collaboration between our data projects and all other projects to drive innovation in data, analytics, and AI open source technologies." + +LF AI & Data supports projects via a wide range of services, and the first step is joining as an Incubation Project. LF AI & Data will support the neutral open governance for FEAST to help foster the growth of the project. Check out the [Documentation](https://docs.feastsite.wpenginepowered.com/) to start working with FEAST today. Learn more about FEAST on their [GitHub](https://github.com/feast-dev/feast) and be sure to join the [FEAST-Announce](https://lists.lfaidata.foundation/g/feast-announce) and [FEAST-Technical-Discuss](https://lists.lfaidata.foundation/g/feast-technical-discuss) mail lists to join the community and stay connected on the latest updates. + +A warm welcome to FEAST! We look forward to the project's continued growth and success as part of the LF AI & Data Foundation. To learn about how to host an open source project with us, visit the [LF AI & Data website](https://lfaidata.foundation/proposal-and-hosting/). + +FEAST Key Links: +* [Website](https://feastsite.wpenginepowered.com/) +* [GitHub](https://github.com/feast-dev/feast) diff --git a/docs/blog/feast-release-0-12-adds-aws-redshift-and-dynamodb-stores.md b/docs/blog/feast-release-0-12-adds-aws-redshift-and-dynamodb-stores.md new file mode 100644 index 00000000000..c79008caaf8 --- /dev/null +++ b/docs/blog/feast-release-0-12-adds-aws-redshift-and-dynamodb-stores.md @@ -0,0 +1,46 @@ +# Feast 0.12 adds AWS Redshift and DynamoDB stores + +*August 11, 2021* | *Jules S. Damji, Tsotne Tabidze, and Achal Shah* + +We are delighted to announce [Feast 0.12](https://github.com/feast-dev/feast/blob/master/CHANGELOG.md) is released! With this release, Feast users can take advantage of AWS technologies such as Redshift and DynamoDB as feature store backends to power their machine learning models. We want to share three key additions that extend Feast's ecosystem and facilitate a convenient way to group features via a Feature Service for serving: + +1. Adding [AWS Redshift](https://aws.amazon.com/redshift/), a cloud data warehouse, as an offline store, which supports features serving for training and batch inference at high throughput + +Let's briefly take a peek at each and how easily you can use them through simple declarative APIs and configuration changes. + +### AWS Redshift as a feature store data source and an offline store + +Redshift data source allows you to fetch historical feature values from Redshift for building training datasets and materializing features into an online store (see below how to materialize). A data source is defined as part of the [Feast Declarative API](https://rtd.feastsite.wpenginepowered.com/en/latest/) in the feature repo directory's Python files. For example, `aws_datasource.py` defines a table from which we want to fetch features. + +```python +from feast import RedshiftSource + +my_redshift_source = RedshiftSource(table="redshift_driver_table") +``` + +### AWS DynamoDB as an online store + +To allow teams to scale up and support high volumes of online transactions requests for machine learning (ML) predictions, Feast now supports a scalable DynamoDB to serve fresh features to your model in production in the AWS cloud. To enable DynamoDB as your online store, just change `featore_store.yaml`: + +```yaml +project: fraud_detection +registry: data/registry.db +provider: aws +online_store: + type: dynamodb + region: us-west-2 +``` + +To materialize your features into your DynamoDB online store, simply issue the command: + +```bash +$ feast materialize +``` + +Use a Feature Service when you want to logically group features from multiple Feature Views. This way, when requested from Feast, all features will be returned from the feature store. `feature_store.get_historical_features(...)` and `feature_store.get_online_features(...)` + +### What's next + +We are working on a Feast tutorial use case on AWS, meanwhile you can check out other [tutorials in documentation](https://docs.feastsite.wpenginepowered.com/). For more documentation about the aforementioned features, check the following Feast links: + +* [Online stores](https://docs.feastsite.wpenginepowered.com/reference/online-stores/) diff --git a/docs/blog/feast-supports-vector-database.md b/docs/blog/feast-supports-vector-database.md new file mode 100644 index 00000000000..6463a271ae3 --- /dev/null +++ b/docs/blog/feast-supports-vector-database.md @@ -0,0 +1,43 @@ +# Feast Launches Support for Vector Databases 🚀 + +*July 25, 2024* | *Daniel Dowler, Francisco Javier Arceo* + +## Feast and Vector Databases + +With the rise of generative AI applications, the need to serve vectors has grown quickly. We are pleased to announce that Feast now supports (as an experimental feature in Alpha) embedding vector features for popular GenAI use-cases such as RAG (retrieval augmented generation). + +An important consideration is that GenAI applications using embedding vectors stand to benefit from a formal feature framework, just as traditional ML applications do. We are excited about adding support for embedding vector features because of the opportunity to improve GenAI backend operations. The integration of embedding vectors as features into Feast, allows GenAI developers to take advantage of MLOps best practices, lowering development time, improving quality of work, and sets the stage for [Retrieval Augmented Fine Tuning](https://techcommunity.microsoft.com/t5/ai-ai-platform-blog/retrieval-augmented-fine-tuning-raft-with-azure-ai/ba-p/3979114). + +## Setting Up a Document Embedding Feature View + +The [feast-workshop repo example](https://github.com/feast-dev/feast-workshop/tree/main) shows how Feast users can define feature views with vector database sources. They can easily convert text queries to embedding vectors, which are then matched against a vector database to retrieve closest vector records. All of this works seamlessly within the Feast toolset, so that vector features become a natural addition to the Feast feature store solution. + +Defining a feature backed by a vector database is very similar to defining other types of features in Feast. Specifically, we can use the FeatureView class with an Array type field. + +```python +from datetime import timedelta +from feast import FeatureView +from feast.types import Array, Float32 +from feast.field import Field + +for key, value in sorted(features.items()): + print(key, " : ", value) + +print_online_features(features) +``` + +## Supported Vector Databases + +The Feast development team has conducted preliminary testing with the following vector stores: + +* SQLite +* Postgres with the PGVector extension +* Elasticsearch + +There are many more vector store solutions available, and we are excited about discovering how Feast may work with them to support vector feature use-cases. We welcome community contributions in this area–if you have any thoughts feel free to join the conversation on GitHub + +## Final Thoughts + +Feast brings formal feature operations support to AI/ML teams, enabling them to produce models faster and at higher levels of quality. The need for feature store support naturally extends to vector embeddings as features from vector databases (i.e., online stores). Vector storage and retrieval is an active space with lots of development and solutions. We are excited by where the space is moving, and look forward to Feast's role in operationalizing embedding vectors as first class features in the MLOps ecosystem. + +If you are new to feature stores and MLOps, this is a great time to give Feast a try. Check out [Feast documentation](https://feast.dev/) and the [Feast GitHub](https://github.com/feast-dev/feast) page for more on getting started. Big thanks to [Hao Xu](https://www.linkedin.com/in/hao-xu-a04436103/) and the community for their contributions to this effort. diff --git a/docs/blog/go-feature-server-benchmarks.md b/docs/blog/go-feature-server-benchmarks.md new file mode 100644 index 00000000000..1bd2539cab2 --- /dev/null +++ b/docs/blog/go-feature-server-benchmarks.md @@ -0,0 +1,55 @@ +# Go feature server benchmarks + +*July 19, 2022* | *Felix Wang* + +## Background + +The Feast team published a [blog post](https://feastsite.wpenginepowered.com/blog/feast-benchmarks/) several months ago with latency benchmarks for all of our online feature retrieval options. Since then, we have built a Go feature server. It is currently in alpha mode, and only supports Redis as an online store. The docs are [here](https://docs.feastsite.wpenginepowered.com/reference/feature-servers/go-feature-server/). We recommend teams that require extremely low-latency feature serving to try the Go feature server. To test it, we ran our benchmarks against it; the results are presented below. + +## Benchmark Setup + +See [https://github.com/feast-dev/feast-benchmarks](https://github.com/feast-dev/feast-benchmarks) for the exact benchmark code. The feature servers were deployed in Docker on AWS EC2 instances (c5.4xlarge, 16vCPU, 64GiB memory). + +## Data and query patterns + +Feast's feature retrieval primarily manages retrieving the latest values of a given feature for specified entities. In this benchmark, the online stores contain: + +* 25 feature views (with 10 features per feature view) for a total of 250 features +* 1M entity rows + +As described in [RFC-031](https://docs.google.com/document/d/12UuvTQnTTCJ), we simulate different query patterns by additionally varying by number of entity rows in a request (i.e. *batch size*), requests per second, and the concurrency of the feature server. The goal here is to have numbers that apply to a diverse set of teams, regardless of their scale and typical query patterns. Users are welcome to extend the benchmark suite to better test their own setup. + +## Online store setup + +These benchmarks only used Redis as an online store. We used a single Redis server, run locally with Docker Compose on an EC2 instance. This should closely approximate usage of a separate Redis server in AWS. Typical network latency within the same availability zone in AWS is [< 1-2 ms](https://aws.amazon.com/blogs/architecture/improving-performance-and-reducing-cost-using-availability-zone-affinity/). In these benchmarks, we did not hit limits that required use of a Redis cluster. With higher batch sizes, the benchmark suite would likely only work with Redis clusters. Redis clusters should improve Feast's performance. + +## Benchmark Results + +### Summary + +* The Go feature server is very fast (e.g. p99 latency is ~3.9 ms for a single row fetch of 250 features) +* For the same number of features and batch size, the Go feature server is about 3-5x faster than the Python feature server + * Despite this, there are still compelling reasons to use Python, depending on your situation (e.g. simplicity of deployment) +* Feature server latency… + * scales linearly (moderate slope) with batch size + * scales linearly (low slope) with number of features + * does not substantially change as requests per seconds increase + +### Latency when varying by batch size + +For this comparison, we check retrieval of 50 features across 5 feature views. At p99, we see that Go significantly outperforms Python, by ~3-5x. It also scales much better with batch size. + +| Batch size | 1 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 | +|------------|---|----|----|----|----|----|----|----|----|----|----| +| Python | 7.23 | 15.14 | 23.96 | 32.80 | 41.44 | 50.43 | 59.88 | 94.57 | 103.28 | 111.93 | 124.87 | +| Go | 4.32 | 3.88 | 6.09 | 8.16 | 10.13 | 12.32 | 14.3 | 16.28 | 18.53 | 20.27 | 22.18 | + +### Latency when varying by number of requested features + +The Go feature server scales a bit better than the Python feature server in terms of supporting a large number of features: +p99 retrieval times (ms), varying by number of requested features (batch size = 1) + +| Num features | 50 | 100 | 150 | 200 | 250 | +|-------------|----|----|-----|-----|-----| +| Python | 8.42 | 10.28 | 13.36 | 16.69 | 45.41 | +| Go | 1.78 | 2.43 | 2.98 | 3.33 | 3.92 | diff --git a/docs/blog/how-danny-chiao-is-keeping-feast-simple.md b/docs/blog/how-danny-chiao-is-keeping-feast-simple.md new file mode 100644 index 00000000000..24955b5aa8c --- /dev/null +++ b/docs/blog/how-danny-chiao-is-keeping-feast-simple.md @@ -0,0 +1,31 @@ +# How Danny Chiao is Keeping Feast Simple + +*March 2, 2022* | *Claire Besset* + +Tecton Engineer Danny Chiao recently appeared on *The Feast Podcast* to have a conversation with host Demetrios Brinkmann, head of the [MLOps Community](https://mlops.community). Demetrios and Danny spent an hour together discussing why Danny left Google to work on Feast, what it's like to be a leader in an open-source community, and what the future holds for Feast and MLOps. You can read about the highlights from their conversation below, or listen to the full episode [here](https://anchor.fm/featurestore). + +## From Google to Feast + +Prior to joining Tecton, Danny spent 7.5 years at Google, working on everything from Google+ to Android to Google Workspace. As a machine learning engineer, he worked with stakeholders from both product and research teams. Bridging gaps between these teams was a two-way challenge: product teams needed help applying learnings from research teams, and research teams needed to be convinced to take on projects from the product space. + +In addition, it was difficult to share data from enterprise Google products with research teams due to security and privacy mandates. Danny's experience working on multiple ML products and interfacing between diverse stakeholder groups would later prove to be highly valuable in his role in the Feast open source community. + +What prompted Danny to leave Google and join Tecton? He noticed how the ML landscape outside of Google was starting to look very different from how it did internally. While Google was still using ETL jobs to read data from data lakes or databases and perform massive transformations, other companies were taking advantage of new data warehouse technologies: "I was hearing that the ecosystem for iterating, developing, and shipping models was oddly enough more mature outside of Google…Internally, a lot of these massive systems are dependent on the infrastructure, so you can't iterate as quickly." + +Excited by the innovations in ML infrastructure that were appearing in the broader community, Danny moved to Tecton to work on [Feast](https://www.tecton.ai/blog/feast-announcement/), an open-source feature store. [Feature stores](https://www.tecton.ai/blog/what-is-a-feature-store/) act as a central hub for feature data across an ML project's lifecycle, and are responsible for transforming raw data into features, storing and managing features, and serving features for training and prediction. Feature stores are quickly becoming a critical infrastructure for data science teams putting ML into production. + +## What it's like to work in the Feast open source community + +As a leader in the Feast community, Danny splits his time between engineering projects and community engagement. In working with the community, Danny is learning about the current and emerging use cases for Feast. One of the big challenges with Feast is its broad user-base: "We have users coming to us like, 'Hey, I don't have that much data. I don't have super-strict latency requirements. I don't need a lot of complexity.' Then you have the Twitters of the world who are like, 'Hey, we need massive scale, massive low latency.' There's definitely that tug." + +There are also diverse usecases for Feast, from recommender systems, to fraud detection, to credit scoring, to biotech. The solution has been to keep Feast as simple and streamlined as possible. It should be flexible and extensible enough to meet the needs of its broad community, but it also aims to be accessible for small companies just beginning machine learning operations. As Danny says, "You can't get all these new users to come in and enjoy value if it's going to take a really, really long time to stand something up." + +This was the vision behind the release of Feast 0.10, which is Python-centric and can run on a developer's local machine. Overall, Danny holds a very positive outlook on the future of collaboration within Feast, noting how the diversity of the community can be an asset: "If you can motivate the right people and drive people towards the same vision, then you can do things way faster than if you were just a small team executing on it." + +## The future for Feast + +What's on the docket for Feast development this year? They're working with companies like Twitter and Redis to get benchmarks on how performant Feast is and harden the serving layer. Danny's excited to work on data quality monitoring and make that practice more standardized in the community. He's also looking forward to the launch of the Feast Web UI, because users have been asking for easier ways to discover and share features and data pipelines. + +True to the vision of keeping Feast simple, the team is focused on targeting new users in the ML space and getting them from zero-to-one. This is the plan for a world where machine learning is becoming even more ubiquitous. "It's going to become something that is just expected of companies," Demetrios said. "Right now, it doesn't feel like we've even gotten at 2% of what is potentially possible if every single business is going to be using machine learning." Fortunately, feature stores are a technology that can dramatically shorten the time it takes a new company to begin realizing value from machine learning. + +From meeting the machine learning needs of a broad user base to helping new teams get started with ML, there's a lot of exciting work to be done at Feast! You can learn more about the Feast project on our [website](https://www.tecton.ai/feast/), or read updates in Danny's community newsletter on the [Feast google group](https://groups.google.com/g/feast-dev/). diff --git a/docs/blog/kubeflow-and-feast-with-david-aronchick.md b/docs/blog/kubeflow-and-feast-with-david-aronchick.md new file mode 100644 index 00000000000..ca8ec914696 --- /dev/null +++ b/docs/blog/kubeflow-and-feast-with-david-aronchick.md @@ -0,0 +1,31 @@ +# Kubeflow + FEAST With David Aronchick, Co-creator of Kubeflow + +*April 29, 2022* | *demetrios* + +A recent episode of *The Feast Podcast* featured the co-creator of [Kubeflow](https://www.kubeflow.org/), David Aronchick, along with hosts Willem Pienaar and Demetrios Brinkmann. David, Willem, and Demetrios talked about the complexities of setting up machine learning (ML) infrastructure today and what's needed in the future to improve this process. You can read about the highlights from the podcast below or listen to the full episode [here](https://anchor.fm/featurestore/episodes/Kubeflo...). + +## Creation and philosophy behind Kubeflow + +[Kubeflow](https://www.kubeflow.org/) is a project that improves the deployment process of ML workflows on [Kubernetes](https://kubernetes.io/), a system for managing containers. It's an open-source platform originally based on Google's internal method to deploy [TensorFlow](https://www.tensorflow.org/) models, and is available for public use. It can deploy systems everywhere that Kubernetes is supported: e.g. on-premise installations, Google Cloud, AWS, and Azure. + +For machine learning practitioners, training is usually done in one of two ways. If the data set is small, users typically work in a Jupyter notebook, which allows them to quickly iterate on the necessary parameters without having to do much manual setup. On the other hand, if the data set is very large, distributed training is required with many physical or virtual machines. + +Originally, Kubeflow started as a way to connect the two worlds, so one could start with a Jupyter notebook and then move into distributed training with more features, pipelines, and feature stores as the data set grows. By itself, Kubeflow did not provide these additional capabilities, but wanted to partner with a service that did — hence, the beginning of a great collaboration with [Feast](https://www.tecton.ai/feast/). David described how Kubeflow is built on a mix of services: Kubeflow defines the pipeline language, Feast provides the feature store, [Argo](https://argoproj.github.io/workflows/) does work under the hood, [Katib](https://www.kubeflow.org/docs/components/katib/...) provides a hyperparameter sweep, and [Seldon](https://www.kubeflow.org/docs/external-add-ons/...) provides an inference endpoint. As Kubeflow becomes more mature, the goal is to restructure from a monolithic infrastructure where many services are installed at once to become more clean and specialized, so users only install the services they need. Currently we can see that happening with the graduation of KServe. + +## Improving the collaboration between data scientists and software engineers + +Next, David discussed how data scientists and software engineers work together to build and deploy ML systems. Data scientists fine tune the parameters of the model while engineers work on productionizing the model — that is, making sure it runs smoothly without interruptions. Unfortunately, the production deploy process cannot be fully automated yet. One of the core problems is that the APIs for ML systems are complicated to use, which is a hindrance to data scientists. + +A lot of work in ML is closer to science, where hypotheses are made and tested, as opposed to software development, where there is an iterative process and new versions are always being shipped. If you start building a distributed model based on a large data set, it may be hard or impossible to work in an interactive notebook like Jupyter unless a completely new, smaller, model is created. + +The general process for ML practitioners is a pipeline, but the individual steps are often not clearly described so it is difficult to map each step to the correct tool for the job. A data scientist's daily work can often look like downloading a CSV, deleting a column of data, uploading it to a feature store, running a Python script, and then doing training. Willem stated the need for a better solution: "Small groups should be able to independently deploy solutions for specific use cases that solve business problems." David wants to make this pipeline easier to perform with existing tools: "While there certainly are components of that available in Kubeflow and Kubernetes and others, I'm thinking about what that next abstraction layer looks like and it should be available shortly." + +## What's needed to accelerate the industry + +The landscape of ML operations platforms is very complex. There are several infrastructure options out there: Kubernetes was chosen as the backbone of Kubeflow because it's simple to set up and tweak. Willem talked about the consolidation of ML and ML operations tools: "It's going to happen eventually because there's just too many out there, and they're not all going to make it. Right now, it's the breeding grounds, and then it's going to be survival of the fittest." We can already see this playing out with DataRobot acquiring Algorithmia, Snowflake purchasing Streamlit and a few days ago, Databricks buying Cortex Labs. + +For open-source projects like Kubeflow, there should be a working group around core components that establishes standards. It isn't necessary to have one person who makes all of the decisions in this space. If a new feature is needed, code discussions are 10% of the problem but the majority of the work is around deciding implementation details and making sure that it works. The fastest way to get something done is just to build it yourself and try to get it merged. + +David mentioned that to really improve the ecosystem for ML, we "need to develop not just a standard layer for describing the entire platform, but also a system that describes many of the common objects in machine learning: a feature, a feature store, a data set, a training run, an experiment, a serving inference, and so on. It will spur innovation because it defines a set of clear contracts that users can produce and consume." Currently, this is hard to do programmatically because the variety of systems means that auxiliary tools need to be written to connect data sets. + +If expanding the future of ML infrastructure sounds exciting to you, there's a lot of contributions that are needed! You can learn more about [Feast](https://www.tecton.ai/feast/), the feature store connected to Kubeflow, and start using it today. Jump in our [slack](http://slack.feastsite.wpenginepowered.com/) and say hi! diff --git a/docs/blog/machine-learning-data-stack-for-real-time-fraud-prediction-using-feast-on-gcp.md b/docs/blog/machine-learning-data-stack-for-real-time-fraud-prediction-using-feast-on-gcp.md new file mode 100644 index 00000000000..729787dc4a2 --- /dev/null +++ b/docs/blog/machine-learning-data-stack-for-real-time-fraud-prediction-using-feast-on-gcp.md @@ -0,0 +1,50 @@ +# Machine learning data stack for real-time fraud detection using Feast on GCP + +*September 8, 2021* | *Jay Parthasarthy and Jules S. Damji* + +A machine learning (ML) model decides whether your transaction is blocked or approved every time you purchase using your credit card. Fraud detection is a canonical use case for real-time ML. Predictions are made upon each request quickly while you wait at a point of sale for payment approval. + +Even though this is a common problem with ML, companies often build custom tooling to tackle these predictions. Like most ML problems, the hard part of fraud prediction is in the data. The fundamental data challenges are the following: + +1. Some data needed for prediction is available as part of the transaction request. This data is the easy part of passing to the model. +2. Other data (for example, a user's historical purchases) provides a high signal for predictions, but it isn't available as part of the transaction request. This data takes time to look up: it's stored in a batch system like a data warehouse. This data is challenging to fetch since it requires a system to handle many queries per second (QPS). +3. Together, they comprise ML features as signals to the model for predicting whether the requested transaction is fraudulent. + +[Feast](https://feastsite.wpenginepowered.com/) is an open-source feature store that helps teams use batch data for real-time ML applications. It's used as part of fraud [prediction and other high-volume transactions systems](https://www.youtube.com/watch?v=ED81DvicQuQ) to prevent fraud for billions of dollars worth of transactions at companies like [Gojek](https://www.gojek.com/en-id/) and [Postmates](https://postmates.com/). In this blog, we discuss how we can use Feast to build a stack for fraud predictions. You can also follow along on Google Cloud Platform (GCP) by running this [Colab tutorial notebook](https://colab.research.google.com/github/feast-dev/feast-fraud-tutorial). + +## Generic data stack for fraud detection + +Here's what a generic stack for fraud prediction looks like: + +## 1. Generating batch features from data sources + +The first step in deploying an ML model is to generate features from raw data stored in an offline system, such as a data warehouse (DWH) or a modern data lake. After that, we use these features in our ML model for training and inference. But before we get into the specifics of fraud detection related to our example below, let's quickly understand some high-level concepts. + +Data sources: This data repository records all historical transactions data for a user, account information, and any indication of user fraud history. Usually, it's a data warehouse (DHW) with respective tables. The diagram above shows that features are generated from these data sources and put into another offline store (or the same store). Using transformational queries, like SQL, this data, joined from multiple tables, could be injected or stored as another table in a DWH— refined and computed as features. + +Features used: In the fraud use case, one set of the raw data is a record of historical transactions. This record includes data about the transaction: +* Amount of transaction +* Timestamp when the event occurred +* User account information + +## 3. Materialize features to low-latency online stores + +We have a model that's ready for real-time inference. However, we won't be able to make predictions in real-time if we need to fetch or compute data out of the data warehouse on each request because it's slow. + +Feast allows you to make real-time predictions based on warehouse data by materializing it into an [online store](https://docs.feastsite.wpenginepowered.com/concepts/registry). Using the Feast CLI, you can incrementally materialize your data, from the current time on since the previous materialized data: + +```bash +feast materialize-incremental $(date -u +"%Y-%m-%dT%H:%M:%S") +``` + +With our feature values loaded into the online store, a low-latency key-value store, as shown in the diagram above, we can retrieve new data when a new transaction request arrives in our system. + +Note that the feast materialize-incremental command needs to be run regularly so that the online store can continue to contain fresh feature values. We suggest that you integrate this command into your company's scheduler (e.g., Airflow.) + +## Conclusion + +In summation, we outlined a general data stack for real-time fraudulent prediction use cases. We implemented an end-to-end fraud prediction system using [Feast on GCP](https://github.com/feast-dev/feast-fraud-tutorial) as part of our tutorial. + +We'd love to hear how your organization's setup differs. This setup roughly corresponds to the most common patterns we've seen from our users, but things are usually more complicated as teams introduce feature logging, streaming features, and operational databases. + +You can bootstrap a simple stack illustrated in this blog by running our [tutorial notebook on GCP](https://colab.research.google.com/github/feast-dev/feast-fraud-tutorial). From there, you can integrate your prediction service into your production application and start making predictions in real-time. We can't wait to see what you build with Feast, and please share with the [Feast community](http://slack.feastsite.wpenginepowered.com/). diff --git a/docs/blog/performance-test-for-python-based-feast-feature-server.md b/docs/blog/performance-test-for-python-based-feast-feature-server.md new file mode 100644 index 00000000000..f9ef252e932 --- /dev/null +++ b/docs/blog/performance-test-for-python-based-feast-feature-server.md @@ -0,0 +1,61 @@ +# Performance Test for the Python-Based Feast Feature Server: Comparison Between DataStax Astra DB (Based on Apache Cassandra), Google Datastore & Amazon DynamoDB + +*April 17, 2023* | *Stefano Lottini* + +## Introduction + +Feature stores are an essential part of the modern stack around machine learning (ML); in particular, the effort aimed at rationalizing the access patterns to the features associated with ML models by the various functions revolving around it (from data engineers to data scientists). At its core, a feature store provides a layer atop a persistent data store (a database) that facilitates shared access to the features associated with the entities belonging to a business domain, making it easier to retrieve them consistently for both training and prediction. + +Out of several well-established feature stores available today, the most popular open-source solution is arguably [Feast](https://feastsite.wpenginepowered.com/). With its active base of contributors and support for a growing list of backends to choose from, ML practitioners don't have to worry about the boilerplate setup of their data system and can focus on delivering their product—all while retaining the freedom to choose the backend that best suits their needs. + +Last year, the Feast team published [extensive benchmarks](https://feastsite.wpenginepowered.com/blog/feast-benchmarks/) comparing the performance of the feature store when using different storage layers for retrieval of "online" features (that is, up-to-date reads to calculate inferences, as opposed to batch or historical "offline" reads). The storage backends used in the test, each powered by its own Feast plugin, were: Redis (running locally), Google Datastore, and Amazon DynamoDB—the latter on the same cloud region as the testing client. The main takeaways were: + +* Redis yields the lowest response times (but at a cost; see below) +* Among the cloud DB vendors, DynamoDB is noticeably faster than Datastore +* Latencies increase with the number of features needed and, albeit less so, with the number of rows ("entities") + +Moreover, Feast offers an SDK for both Java and Python. Although choosing the Java stack for the feature server results in faster responses, the vast majority of Feast users work with a Python-centered stack. So in our tests, we'll focus on Python start-to-end setups. + +Surveys done by Feast also showed that more than 60% of the interviewees required that P99 latency stay below 50 ms. These ultra-low-latency ML use cases often fall in the [fraud detection](https://www.tecton.ai/blog/how-to-build-a-fraud-detection-ml-system/) and [recommender system](https://www.tecton.ai/blog/guide-to-building-online-recommender-systems/) categories. + +## Feature stores & Cassandra / Astra DB + +The need for persistent data stores is ubiquitous in any ML application—and it comes in all sizes and shapes, of which the "feature store" pattern is but a certain, albeit very common, instance. As is discussed at length in the Feast blog post, many factors influence the architectural choices for ML-based systems. Besides serving latency, there are considerations about fault tolerance and data redundancy, ease of use, pricing, ease of integration with the rest of the stack, and so forth. For example, in some cases, it may be convenient to employ an in-memory store such as Redis, trading data durability and ease of scaling for reduced response times. + +In this [recently published guide](https://planetcassandra.org/post/practitioners-guide-to-cassandra-for-ml/), the author highlights the fact that a feature store lies at the core of most ML-centered architectures lies, possibly (and, looking forward, more and more so) augmented with real-time capabilities owing to a combination of CDC (Change Data Capture), event-streaming technologies, and sometimes in-memory cache layers. The guide makes the case that Cassandra and DataStax's cloud-based DBaaS [Astra DB](https://astra.datastax.com/) (which is built on Cassandra) are great databases to build a feature store on top of, owing to the world-class fault tolerance, 100% uptime, and extremely low latencies it can offer out of the box. + +We then set out to extend the performance measurements to Astra DB, with the intent to provide hard data corroborating our claim that Cassandra and Astra DB are performant first-class choices for an online feature store. In other words, once the plugin made its way to Feast, we took the next logical step: running the very same testing already done for the other DBaaS choice, but this time on Astra DB. The next section reports on our findings. + +## Performance benchmarks for Feast on Astra DB + +The Feast team published a Github [repository](https://github.com/feast-dev/feast-benchmarks) with the code used for the benchmarks. We added coverage for Astra DB (plus a one-node Cassandra cluster running locally, serving the purpose of a functional test) and upgraded the Feast version used in all benchmarks to use v0.26 consistently. + +*Note: The original tests used v0.20 for DynamoDB, v0.17 for Datastore and v0.21 for Redis. Because we reproduced all pre-existing benchmarks, finding most values to be in acceptable agreement (see below for more remarks on this point), we are confident that upgrading the Feast version does not significantly alter the performance.* + +The tests have been run on comparable AWS and GCP machines (respectively c5.4xlarge and c2-standard-16 instances) running in the same region as the cloud database (thereby mimicking the desired architecture for a production system). We did not change any benchmark parameter in order to keep the comparison meaningful, even with prior results. As stated earlier, we focused on the Python feature server, which has a wider adoption among the Feast community and supports a broader ecosystem of plugins. + +Here's how we conducted the benchmarking. First, a moderate amount of synthetic "feature data" (10k entities with 250 integer features each, for a total of about 11 MB) was materialized to the online store. Then various one-minute test runs were performed, each with a certain choice of feature-retrieval parameters, all while collecting statistics (in particular, high percentiles) on the response time of these retrieval operations. The parameters that varied between runs were: + +* batch size (1 to 100 entities per request) + +Let's go back to the Cassandra plugin for Feast and examine some properties of how it was structured. + +First, one might notice that, regardless of which features are requested at runtime, the whole partition (i.e., all features for a given entity) is read. This was chosen to avoid using IN clauses when querying Cassandra; these are indeed discouraged unless the number of values is very, very small (as a rule of thumb, less than half a dozen). Moreover, since one does not know at write-time which features will be read together, there is no preferred way to arrange the clustering column(s) to have these features grouped together in the partition (as done, for example, with Facebook's ["feature re-ordering"](https://engineering.fb.com/2022/09/19/ml-applications/feature-store-announcement/) which purportedly results in a 30%-70% latency reduction). A reasonable compromise was then to always read the whole partition and apply client-side post-query filtering to avoid burdening the query coordinators with additional work—at the cost, of course, of increased network throughput. + +Second, when features from multiple entities are needed, the plugin makes good use of the execute_concurrently_with_args primitive offered by the Cassandra Python driver, thereby spawning one thread per partition and firing all requests at once (up to a maximum concurrency threshold, which can be configured). This leverages the excellent support for concurrency by the Cassandra architecture, which accounts for the observed moderate dependency of latencies on the batch size. + +## Conclusion + +We put the Cassandra plugin for Feast to test in the same way as other DBaaS plugins were tested; that is, using the Astra DB cloud database built on Cassandra, and we ran the same benchmarks that were applied to Redis, Datastore, and DynamoDB. + +Besides broadly confirming the previous results published by the Feast team, our main finding is that the performance with Astra DB is on par with that of AWS DynamoDB and noticeably better than that of Google Datastore. + +All these tests target the Python implementation. As mentioned in the Feast article, switching to a Java feature server greatly improves the performance, but requires a more convoluted setup and architecture and overall more expertise both for setup and maintenance. + +Other evidence points to the fact that, *if one is mainly concerned about performance*, replacing any feature store with a direct-to-DB implementation may be the best choice. In this regard, our extensive investigations clearly make the case that Cassandra is a good fit for ML applications, regardless of whether a feature store is involved or not. + +Some results might be made statistically stronger by more extensive tests, which could be a task for a future iteration of these performance benchmarks. It is possible that longer runs and/or much larger amounts of stored data would better highlight the underlying patterns in how the response times behave as a function of batch size and/or number of requested features. + +## Acknowledgements + +The author would like to thank Alan Ho, Scott Regan, and Jonathan Shook for a critical reading of this manuscript, and the Feast team for a pleasant and fruitful collaboration around the development (first) and the benchmarking (afterwards) of the Cassandra / Astra DB plugin for the namesake feature store. diff --git a/docs/blog/rbac-role-based-access-controls.md b/docs/blog/rbac-role-based-access-controls.md new file mode 100644 index 00000000000..683dd9c6940 --- /dev/null +++ b/docs/blog/rbac-role-based-access-controls.md @@ -0,0 +1,71 @@ +# Feast Launches Role Based Access Control (RBAC)! 🚀 + +*November 21, 2024* | *Daniele Martinoli, Francisco Javier Arceo* + +Feast is proud to introduce Role-Based Access Control (RBAC), a game-changing feature for secure and scalable feature store management. With RBAC, administrators can define granular access policies, ensuring each team has the appropriate permissions to access and manage only the data they need. Built on Kubernetes RBAC and OpenID Connect (OIDC), this powerful model enhances data governance, fosters collaboration, and makes Feast a trusted solution for teams handling sensitive, proprietary data. + +## What is the Feast Permission Model? + +Feast now supports Role Based Access Controls (RBAC) so you can secure and govern your data. If you ever wanted to securely partition your feature store across different teams, the new Feast permissions model is here to make that possible! + +This powerful feature allows administrators to configure granular authorization policies, letting them decide which users and groups can access specific resources and what operations they can perform. + +The default implementation is based on Role-Based Access Control (RBAC): user roles determine whether a user has permission to perform specific functions on registered resources. + +## Why is RBAC important for Feast? + +Feature stores often operate on sensitive, proprietary data and we want to make sure teams are able to govern the access and control of that data thoughtfully, while benefiting from transparent code and an open source community like Feast. + +That's why we built RBAC using [Kubernetes RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) and [OpenID Connect protocol (OIDC)](https://auth0.com/docs/authenticate/protocols/openid-connect), ensuring secure, fine-grained access control in Feast. + +## What are the Benefits of using Feast Permissions? + +Using the Feast Permissions Model offers two key benefits: + +1. Securely share and partition your feature store: grant each team only the minimum privileges necessary to access and manage the relevant resources. +2. Adopt a Service-Oriented Architecture and leverage the benefits of a distributed system. + +## How Feast Uses RBAC + +### Permissions as Feast resources + +The RBAC configuration is defined using a new Feast object type called "Permission". Permissions are registered in the Feast registry and are defined and applied like all the other registry objects, using Python code. + +A permission is defined by these three components: + +* A resource: a Feast object that we want to secure against unauthorized access. It's identified by the matching type(s), a possibly empty list of name patterns and a dictionary of required tags. +* An action: a logical operation performed on the secured resource, such as managing the resource state with CREATE, DESCRIBE, UPDATE or DELETE, or accessing the resource data with READ and WRITE (differentiated by ONLINE and OFFLINE store types) +* A policy: the rule to enforce authorization decisions based on the current user. The default implementation uses role-based policies. + +The resource types supported by the permission framework are those defining the customer feature store: + +* Project +* Entity +* Clients use the feature store transparently, with authorization headers automatically injected in every request. +* Service-to-service communications are permitted automatically. + +Currently, only the following Python servers are supported in an authorized environment: +- Online REST feature server +- Offline Arrow Flight feature server +- gRPC Registry server + +### Configuring Feast Authorization + +For backward compatibility, by default no authorizations are enforced. The authorization functionality must be explicitly enabled using the auth configuration section in feature_store.yaml. Of course, all server and client applications must have a consistent configuration. + +Currently, feast supports [OIDC](https://auth0.com/docs/authenticate/protocols/openid-connect) and [Kubernetes RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) authentication/authorization. + +* With OIDC authorization, the client uses an OIDC server to fetch a JSON Web Token (JWT), which is then included in every request. On the server side, the token is parsed to extract user roles and validate them against the configured permissions. +* With Kubernetes authorization, the client injects its service account JWT token into the request. The server then extracts the service account name from the token and uses it to look up the associated role in the Kubernetes RBAC resources. + +### Inspecting and Troubleshooting the Permissions Model + +The feast CLI includes a new permissions command to list the registered permissions, with options to identify the matching resources for each configured permission and the existing resources that are not covered by any permission. + +For troubleshooting purposes, it also provides a command to list all the resources and operations allowed to any managed role. + +## How Can I Get Started? + +This new feature includes working examples for both supported authorization protocols. You can start by experimenting with these examples to see how they fit your own feature store and assess their benefits. + +As this is a completely new functionality, your feedback will be extremely valuable. It will help us adapt the feature to meet real-world requirements and better serve our customers. diff --git a/docs/blog/streaming-feature-engineering-with-denormalized.md b/docs/blog/streaming-feature-engineering-with-denormalized.md new file mode 100644 index 00000000000..ace3ec2df6c --- /dev/null +++ b/docs/blog/streaming-feature-engineering-with-denormalized.md @@ -0,0 +1,135 @@ +# Streaming Feature Engineering with Denormalized + +*December 17, 2024* | *Matt Green* + +Learn how to use Feast with [Denormalized](https://www.denormalized.io/) + +Thank you to [Matt Green](https://www.linkedin.com/in/mgreen9/) and [Francisco Javier Arceo](https://www.linkedin.com/in/franciscojavierarceo) for their contributions! + +## Introduction + +Feature stores have become a critical component of the modern AI stack where they serve as a centralized repository for model features. Typically, they consist of both an offline store for aggregating large amounts of data while training models, and an online store, which allows for low latency delivery of specific features when running inference. + +A popular open source example is [Feast](https://feast.dev/), which allows users to store features together by ingesting data from different data sources. While Feast allows you to define features and query data stores using those definitions, it relies on external systems to calculate and update online features. This post will demonstrate how to use [denormalized](https://www.denormalized.io/) to build real-time feature pipelines. + +The full working example is available at the [feast-dev/feast-denormalized-tutorial](https://github.com/feast-dev/feast-denormalized-tutorial) repo. Instructions for configuring and running the example can be found in the README file. + +## The Problem + +Fraud detection is a classic example of a model that uses real-time features. Imagine you are building a model to detect fraudulent user sessions. One feature you would be interested in is the number of login attempts made by a user and how many of those were successful. You could calculate this feature by looking back in time over a sliding interval (AKA "a sliding window"). If you notice a large amount of failed login attempts over the previous 5 seconds, you might infer the account is being brute-forced and choose to invalidate the session and lock the account. + +To simulate this scenario, we wrote a simple script that emits fake login events to a Kafka cluster: [session_generator](https://github.com/feast-dev/feast-denormalized-tutorial). + +This script will emit json events according to the following schema: + +```python +@dataclass +timestamp: datetime +user_id: str +ip_address: str +success: bool +``` + +## Configuring the Feature Store with Feast + +Before we can start writing our features, we need to first configure the feature store. Feast makes this easy using a Python API. In Feast, features are referred to as Fields and are grouped into FeatureViews. FeatureViews have corresponding PushSources for ingesting data from online sources (i.e., we can push data to Feast). We also define an offline data store using the FileSource class, though we won't be using that in this example. + +```python +file_sources = [] +push_sources = [] +feature_views = [] + +for i in [1, 5, 10, 15]: + file_source = FileSource( + path=str(Path(__file__).parent / f"./data/auth_attempt_{i}.parquet"), + timestamp_field="timestamp", + ) + file_sources.append(file_source) + + push_source = PushSource( + name=f"auth_attempt_push_{i}", + batch_source=file_source, + ) + push_sources.append(push_source) + + feature_views.append( + FeatureView( + name=f"auth_attempt_view_w{i}", + entities=[auth_attempt], + schema=[ + Field(name="user_id", dtype=feast_types.String,), + Field(name="timestamp", dtype=feast_types.String,), + Field(name=f"{i}_success", dtype=feast_types.Int32,), + Field(name=f"{i}_total", dtype=feast_types.Int32,), + Field(name=f"{i}_ratio", dtype=feast_types.Float32,), + ], + source=push_source, + online=True, + ) + ) +``` + +The code creates 4 different FeatureViews each containing their own features. As discussed previously, fraud features can be calculated over a sliding interval. It can be useful to not only look at recent failed authentication attempts but also the aggregate of attempts made over longer time intervals. This could be useful when trying to detect things like credential testing which can happen over a longer period of time. + +In our example, we're creating 4 different FeatureViews that will ultimately be populated by 4 different window lengths. This can help our model detect various types of attacks over different time intervals. Before we can use our features, we'll need to run `feast apply` to set-up the online datastore. + +## Writing the Pipelines with Denormalized + +Now that we have our online data store configured, we need to write our data pipelines for computing the features. Simply speaking, these pipelines need to: + +1. Read messages from Kafka +2. Aggregate those messages over a varied timeframe +3. Write the resulting aggregate value to the feature store + +Denormalized makes this really easy. First, we create our DataStream object from a Context(): + +```python +ds = FeastDataStream( + Context().from_topic( + config.kafka_topic, + feature_service, f"auth_attempt_push*{config.feature_prefix}" + ) +) +``` + +This will start the Denormalized Rust stream processing engine, which is powered by DataFusion so it's ultra-fast. + +## Running Multiple Pipelines + +The write_feast_feature() method is a blocking call that continuously executes one pipeline to produce a set of features across a single sliding window. If we want to calculate features for using different sliding window lengths, will need to configure and start multiple pipelines. We can easily do this using the multiprocessing library in python: + +```python +for window_length in [1, 5, 10, 15]: + config = PipelineConfig( + window_length_ms=window_length * 1000, + slide_length_ms=1000, + feature_prefix=f"{window_length}", + kafka_bootstrap_servers=args.kafka_bootstrap_servers, + kafka_topic=args.kafka_topic, + ) + process = multiprocessing.Process( + target=run_pipeline, + args=(config,), + name=f"PipelineProcess-{window_length}", + daemon=False, + ) + processes.append(process) + +for p in processes: + try: + p.start() + except Exception as e: + logger.error(f"Failed to start process {p.name}: {e}") + cleanup_processes(processes) + return +``` + +For each group of features we defined earlier, we spin up a different system process with a different window length. Each process will then execute its own instance of the Denormalized stream processing engine, which has its own thread pools for effective parallelization of work. + +While this example demonstrates how you can easily run multiple Denormalized pipelines, in a production environment, you'd probably want each pipeline running in its own container. + +## Final Thoughts + +We've demonstrated how you can easily create real-time features using Feast and Denormalized. While working with streaming data can be a challenge, modern python libraries backed by fast native code are making it easier than ever to quickly iterate on model inputs. + +Denormalized is currently in the early stages of development. If you have any feedback or questions, feel free to reach out at [hello@denormalized.io](mailto:hello@denormalized.io). diff --git a/docs/blog/the-future-of-feast.md b/docs/blog/the-future-of-feast.md new file mode 100644 index 00000000000..f08547a1bf7 --- /dev/null +++ b/docs/blog/the-future-of-feast.md @@ -0,0 +1,38 @@ +# The Future of Feast + +*February 23, 2024* | *Willem Pienaar* + +AI has taken center stage with the rise of large language models, but production ML systems remain the lifeblood of most AI powered companies today. At the heart of these products are feature stores like Feast, serving real-time, batch, and streaming data points to ML models. I'd like to spend a moment taking stock on what we've accomplished over the last six years and what the growing Feast community has to look forward to. + +## Act 1: Gojek and Google + +Feast was started in 2018 as a [collaboration](https://cloud.google.com/blog/products/ai-machine-learning/introducing-feast-an-open-source-feature-store-for-machine-learning) between Gojek and our friends at Google Cloud. The primary motivation behind the project was to reign in the rampant duplication of feature engineering across the Southeast Asian decacorn's many ML teams. + +Almost immediately, the key challenge with feature stores became clear: Can it be generalized across various ML use cases? + +The natural way to answer that question is to battle test the software out in the open. So in late 2018, spurred on by our friends in the Kubeflow project, we open sourced Feast. A community quickly formed around the project. This group was mostly made up of software engineers at data rich technology companies, trying to find a way to help their ML teams productionize models at a much higher pace. + +Having a community centric approach is in the DNA of the project. All of our RFCs, discussions, designs, community calls, and code are open source. The project became a vehicle for ML platform teams globally to collaborate. Many teams saw the project as a means of stress testing their internal feature store designs, while others like Agoda, Zulily, Farfetch, and Postmates adopted the project wholesale and became core contributors. + +As time went by the demand grew for the project to have neutral ownership and formal governance. This led to us [entering the project into the Linux Foundation for AI in 2020](https://lfaidata.foundation/blog/2020/11/10/feast-joins-lf-ai-data-as-new-incubation-project/). + +## Act 2: Rise of the Feature Store + +By 2020, the demand for feature stores had reached a fever pitch. If you were dealing with more than just an Excel sheet of data, you were likely planning to either build or buy a feature store. A category formed around feature stores and MLOps. Being a neutrally governed open source project brought in a raft of contributions, which helped the project generalize not just to different data platforms and vendors, but also different use cases and deployment patterns. A few of the highlights include: + +* We worked closely with AI teams at [Snowflake](https://quickstarts.snowflake.com/guide/getting_started_with_feast/), [Azure](https://techcommunity.microsoft.com/t5/ai-customer-engineering-team/using-feast-feature-store-with-azure-ml/ba-p/2908404) + +It's also important to mention that by far the biggest contributor to Feast was [Tecton](https://www.tecton.ai/), who invested considerable resources into the project and helped create the category. + +Today, the project is battle hardened and stable. It's seen adoption and/or contribution from companies like Adyen, Affirm, Better, Cloudflare, Discover, Experian, Lowes, Red Hat, Robinhood, Palo Alto Networks, Porch, Salesforce, Seatgeek, Shopify, and Twitter, just to name a few. + +## Act 3: The Road to 1.0 + +The rate of change in AI has accelerated, and nowhere is it moving faster than in open source. Keeping up with this rate of change for AI infra requires the best minds, so with that we'd like to introduce a set of contributors who will be graduating to official project maintainers: + +* [Francisco Javier Arceo](https://www.linkedin.com/in/franciscojavierarceo/) – Engineering Manager, [Affirm](https://www.affirm.com/) +* [Hao Xu](https://www.linkedin.com/in/hao-xu-a04436103/) – Lead Software Engineer, J.P. Morgan + +Over the next few months these maintainers will focus on bringing the project to a major 1.0 release. In our next post we will take a closer look at what the road to 1.0 looks like. + +If you'd like to get involved, try out the project [over at GitHub](https://github.com/feast-dev/feast) or join our [Slack](https://feastopensource.slack.com) community! diff --git a/docs/blog/the-road-to-feast-1-0.md b/docs/blog/the-road-to-feast-1-0.md new file mode 100644 index 00000000000..27be07aadea --- /dev/null +++ b/docs/blog/the-road-to-feast-1-0.md @@ -0,0 +1,35 @@ +# The road to Feast 1.0 + +*February 28, 2024* | *Edson Tirelli* + +### Past Achievements and a Bright Future + +In the [previous blog](https://feast.dev/blog/the-future-of-feast/) we recapped Feast's journey over the last 6 years and hinted about what is coming in the future. We also announced a new group of maintainers that joined the project to help drive it to the 1.0 milestone. Today, we will drill down a little bit into the goals for the project towards that milestone. + +### The Goals for Feast 1.0 + +* Tighter Integration with [**Kubeflow**](https://www.kubeflow.org/): Recognizing the growing importance of Kubernetes in the ML workflow, a primary objective is to achieve a closer integration with [Kubeflow](https://www.kubeflow.org/). This will enable smoother workflows and enhanced scalability for ML projects. + +* Development of Enterprise Features: With the aim to make Feast more robust for enterprise usage, we are focusing on developing features that cater to the complex needs of large-scale organizations. These include advanced security measures, scalability enhancements, and improved data management capabilities. + +* Graduation from [**LF AI and Data Foundation Incubation**](https://landscape.lfai.foundation/?selected=feast): Currently incubating under the [LF AI and Data Foundation](https://landscape.lfai.foundation/?selected=feast), we are setting our sights on graduating Feast to become a fully-fledged project under the foundation. This step will mark a significant milestone in our journey, recognizing the maturity and stability of Feast. + +* Research and Development for Novel Use Cases: Keeping pace with the rapidly evolving ML landscape (e.g., Large Language Models and Retrieval Augmented Generation), we are committed to exploring new research areas. Our aim is to adapt Feast to support novel use cases, keeping it at the forefront of technology. + +* Support for Latest ML Model Advancements: As ML models become more sophisticated, Feast will evolve to support these advancements. This includes accommodating new model architectures and training techniques. + +This new phase is not just about setting goals but laying down a concrete roadmap to achieve Feast version 1.0. This version will encapsulate all our efforts towards making Feast more integrated, enterprise-ready, and aligned with the latest ML advancements. + +### Why Invest in Feast? + +Many industry applications of machine learning require intensely sophisticated data pipelines. Over the last decade, the data infrastructure and analytics community collaborated together to build powerful frameworks like dbt that enabled analytics to flourish. We believe Feast can do the same for the machine learning community–particularly those that spend most of their time on data pipelining and feature engineering. We believe Feast is a core foundation in the future of machine learning and we will build it to offer a standard set of patterns that will enable ML Engineering and ML Ops teams to leverage those patterns and industry best practices to avoid common pitfalls, while (1) offering the flexibility of choosing their own infrastructure and (2) providing ML Practitioners with a Python-based interface. + +### In Conclusion + +This transition marks a pivotal moment in Feast's journey. We are excited about the opportunities and challenges ahead. With the support of the ML community, the dedication of our new maintainers, and the clear vision set by our steward committee, Feast is poised to reach new heights and continue to be a pivotal tool in the ML ecosystem. + +We invite everyone to join us in this exciting journey and contribute to the future of Feast. Together, let's shape the next chapter in the evolution of feature stores and machine learning. + +For updates and discussions, join our [Slack channel](http://feastopensource.slack.com/) and follow our [GitHub repository](https://github.com/feast-dev/feast/). + +*This post reflects the collective vision and aspirations of the new Feast steward committee. For more detailed discussions and contributions, please reach out to us on our [community channels](https://docs.feast.dev/community).* diff --git a/docs/blog/what-is-a-feature-store.md b/docs/blog/what-is-a-feature-store.md new file mode 100644 index 00000000000..720d6ab1ab2 --- /dev/null +++ b/docs/blog/what-is-a-feature-store.md @@ -0,0 +1,85 @@ +# What is a Feature Store? + +*January 21, 2021* | *Willem Pienaar & Mike Del Balso* + +Blog co-authored with Mike Del Balso, Co-Founder and CEO of Tecton, and cross-posted [here](https://www.tecton.ai/blog/what-is-a-feature-store/) + +Data teams are starting to realize that operational machine learning requires solving data problems that extend far beyond the creation of data pipelines. In [Why We Need DevOps for ML Data](https://www.tecton.ai/blog/devops-ml-data/), Tecton highlighted some of the key data challenges that teams face when productionizing ML systems: + +* Accessing the right raw data +* Building features from raw data +* Combining features into training data +* Calculating and serving features in production +* Monitoring features in production + +Production data systems, whether for large scale analytics or real-time streaming, aren't new. However, *operational machine learning* — ML-driven intelligence built into customer-facing applications — is new for most teams. The challenge of deploying machine learning to production for operational purposes (e.g. recommender systems, fraud detection, personalization, etc.) introduces new requirements for our data tools. + +A new kind of ML-specific data infrastructure is emerging to make that possible. Increasingly Data Science and Data Engineering teams are turning towards feature stores to manage the data sets and data pipelines needed to productionize their ML applications. This post describes the key components of a modern feature store and how the sum of these parts act as a force multiplier on organizations, by reducing duplication of data engineering efforts, speeding up the machine learning lifecycle, and unlocking a new kind of collaboration across data science teams. + +Quick refresher: in ML, a feature is data used as an input signal to a predictive model. For example, if a credit card company is trying to predict whether a transaction is fraudulent, a useful feature might be *whether the transaction is happening in a foreign country*, or *how the size of this transaction compares to the customer's typical transaction*. When we refer to a feature, we're usually referring to the concept of that signal (e.g. "transaction_in_foreign_country"), not a specific value of the feature (e.g. not "transaction #1364 was in a foreign country"). + +## Enter the feature store + +*"The interface between models and data"* + +We first introduced feature stores in our blog post describing Uber's [Michelangelo](https://eng.uber.com/michelangelo-machine-learning-platform/) platform. Feature stores have since emerged as a necessary component of the operational machine learning stack. + +Feature stores make it easy to: +1. Productionize new features without extensive engineering support +2. Automate feature computation, backfills, and logging +3. Share and reuse feature pipelines across teams +4. Track feature versions, lineage, and metadata +5. Achieve consistency between training and serving data +6. Monitor the health of feature pipelines in production + +Feature stores aim to solve the full set of data management problems encountered when building and operating operational ML applications. A feature store is an ML-specific data system that: + +* Runs data pipelines that transform raw data into feature values +* Stores and manages the feature data itself, and +* Serves feature data consistently for training and inference purposes + +Feature stores bring economies of scale to ML organizations by enabling collaboration. When a feature is registered in a feature store, it becomes available for immediate reuse by other models across the organization. This reduces duplication of data engineering efforts and allows new ML projects to bootstrap with a library of curated production-ready features. + +## Components of a Feature Store + +There are 5 main components of a modern feature store: Transformation, Storage, Serving, Monitoring, and Feature Registry. + +In the following sections we'll give an overview of the purpose and typical capabilities of each of these sections. + +## Serving + +Models need access to fresh feature values for inference. Feature stores accomplish this by regularly recomputing features on an ongoing basis. Transformation jobs are orchestrated to ensure new data is processed and turned into fresh new feature values. These jobs are executed on data processing engines (e.g. Spark or Pandas) to which the feature store is connected. + +Model development introduces different transformation requirements. When iterating on a model, new features are often engineered to be used in training datasets that correspond to historical events (e.g. all purchases in the past 6 months). To support these use cases, feature stores make it easy to run "backfill jobs" that generate and persist historical values of a feature for training. Some feature stores automatically backfill newly registered features for preconfigured time ranges for registered training datasets. + +Transformation code is reused across environments preventing training-serving skew and frees teams from having to rewrite code from one environment to the next. Feature stores manage all feature-related resources (compute, storage, serving) holistically across the feature lifecycle. Automating repetitive engineering tasks needed to productionize a feature, they enable a simple and fast path-to-production. Management optimizations (e.g. retiring features that aren't being used by any models, or deduplicating feature transformations across models) can bring significant efficiencies, especially as teams grow increasingly the complexity of managing features manually. + +## Monitoring + +When something goes wrong in an ML system, it's usually a data problem. Feature stores are uniquely positioned to detect and surface such issues. They can calculate metrics on the features they store and serve that describe correctness and quality. Feature stores monitor these metrics to provide a signal of the overall health of an ML application. + +Feature data can be validated based on user defined schemas or other structural criteria. Data quality is tracked by monitoring for drift and training-serving skew. E.g. feature data served to models are compared to data on which the model was trained to detect inconsistencies that could degrade model performance. + +When running production systems, it's also important to monitor operational metrics. Feature stores track operational metrics relating to core functionality. E.g. metrics relating to feature storage (availability, capacity, utilization, staleness) or feature serving (throughput, latency, error rates). Other metrics describe the operations of important adjacent system components. For example, operational metrics for external data processing engines (e.g. job success rate, throughput, processing lag and rate). + +Feature stores make these metrics available to existing monitoring infrastructure. This allows ML application health to be monitored and managed with existing observability tools in the production stack. Having visibility into which features are used by which models, feature stores can automatically aggregate alerts and health metrics into views relevant to specific users, models, or consumers. + +It's not essential that all feature stores implement such monitoring internally, but they should at least provide the interfaces into which data quality monitoring systems can plug. Different ML use cases can have different, specialized monitoring needs so pluggability here is important. + +## Registry + +A critical component in all feature stores is a centralized registry of standardized feature definitions and metadata. The registry acts as a single source of truth for information about a feature in an organization. + +The registry is a central interface for user interactions with the feature store. Teams use the registry as a common catalog to explore, develop, collaborate on, and publish new definitions within and across teams. + +The registry allows for important metadata to be attached to feature definitions. This provides a route for tracking ownership, project or domain specific information, and a path to easily integrate with adjacent systems. This includes information about dependencies and versions which is used for lineage tracking. + +To help with common debugging, compliance, and auditing workflows, the registry acts as an immutable record of what's available analytically and what's actually running in production. + +## Where to go to get started + +We see features stores as the heart of the data flow in modern ML applications. They are quickly proving to be [critical infrastructure](https://a16z.com/2020/10/15/the-emerging-architectures-of-modern-data/) for data science teams putting ML into production. We expect 2021 to be a year of massive feature store adoption, as machine learning becomes a key differentiator for technology companies. + +There are a few options for getting started with feature stores: + +* [Feast](https://feastsite.wpenginepowered.com/) is a great option if you already have transformation pipelines to compute your features, but need a great storage and serving layer to help you use them in production. Feast is GCP/AWS only today, but we're working hard to make Feast available as a light-weight feature store for all environments. Stay tuned. From b24d531bdcd0d5fb633c8cb2b4c233af855be9d6 Mon Sep 17 00:00:00 2001 From: Theodor Mihalache <84387487+tmihalac@users.noreply.github.com> Date: Mon, 10 Feb 2025 10:28:16 -0500 Subject: [PATCH 17/30] docs: Deprecate Helm Operator - docs (#5022) docs: Deprecate Helm Operator Signed-off-by: Theodor Mihalache --- docs/how-to-guides/running-feast-in-production.md | 2 +- infra/feast-helm-operator/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/how-to-guides/running-feast-in-production.md b/docs/how-to-guides/running-feast-in-production.md index 021a10ac1ca..aa277c2540a 100644 --- a/docs/how-to-guides/running-feast-in-production.md +++ b/docs/how-to-guides/running-feast-in-production.md @@ -203,7 +203,7 @@ feature_vector = fs.get_online_features( ).to_dict() ``` -### 4.2. Deploy Feast feature servers on Kubernetes +### 4.2. Deploy Feast feature servers on Kubernetes (Deprecated replaced by [feast-operator](../../infra/feast-operator/README.md)) To deploy a Feast feature server on Kubernetes, you can use the included [helm chart + tutorial](https://github.com/feast-dev/feast/tree/master/infra/charts/feast-feature-server) (which also has detailed instructions and an example tutorial). diff --git a/infra/feast-helm-operator/README.md b/infra/feast-helm-operator/README.md index ba9fe17fa3c..e6d9caee9f5 100644 --- a/infra/feast-helm-operator/README.md +++ b/infra/feast-helm-operator/README.md @@ -1,4 +1,4 @@ -# Feast Feature Server Helm-based Operator +# Feast Feature Server Helm-based Operator (Deprecated replaced by [feast-operator](../feast-operator/README.md)) This Operator was built with the [operator-sdk](https://github.com/operator-framework/operator-sdk) and leverages the [feast-feature-server helm chart](/infra/charts/feast-feature-server). From d937dcb7fc1ea081f9b682f37d99310691094e38 Mon Sep 17 00:00:00 2001 From: Tommy Hughes IV Date: Mon, 10 Feb 2025 16:27:32 -0600 Subject: [PATCH 18/30] chore: Operator / Feast should have matching Data Source types (#5041) data store types Signed-off-by: Tommy Hughes --- .github/workflows/operator_pr.yml | 4 +- .../workflows/pr_local_integration_tests.yml | 6 ++ infra/feast-operator/.golangci.yml | 3 + infra/feast-operator/Makefile | 8 +- .../api/v1alpha1/featurestore_types.go | 11 ++- .../crd/bases/feast.dev_featurestores.yaml | 2 - infra/feast-operator/dist/install.yaml | 2 - infra/feast-operator/docs/api/markdown/ref.md | 4 +- .../test/api/featurestore_types_test.go | 18 +++- .../data-source-types/data-source-types.py | 18 ++++ .../data_source_types_test.go | 88 +++++++++++++++++++ 11 files changed, 145 insertions(+), 19 deletions(-) create mode 100644 infra/feast-operator/test/data-source-types/data-source-types.py create mode 100644 infra/feast-operator/test/data-source-types/data_source_types_test.go diff --git a/.github/workflows/operator_pr.yml b/.github/workflows/operator_pr.yml index 2feed8dbf32..aefdcbdcbb4 100644 --- a/.github/workflows/operator_pr.yml +++ b/.github/workflows/operator_pr.yml @@ -11,8 +11,6 @@ jobs: with: go-version: 1.22.9 - name: Operator tests - run: | - cd infra/feast-operator/ - make test + run: make -C infra/feast-operator test - name: After code formatting, check for uncommitted differences run: git diff --exit-code infra/feast-operator diff --git a/.github/workflows/pr_local_integration_tests.yml b/.github/workflows/pr_local_integration_tests.yml index d3488cd08c3..7fa900b94ed 100644 --- a/.github/workflows/pr_local_integration_tests.yml +++ b/.github/workflows/pr_local_integration_tests.yml @@ -56,3 +56,9 @@ jobs: - name: Test local integration tests if: ${{ always() }} # this will guarantee that step won't be canceled and resources won't leak run: make test-python-integration-local + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: 1.22.9 + - name: Operator Data Source types test + run: make -C infra/feast-operator test-datasources diff --git a/infra/feast-operator/.golangci.yml b/infra/feast-operator/.golangci.yml index bf54dc46026..020e5768657 100644 --- a/infra/feast-operator/.golangci.yml +++ b/infra/feast-operator/.golangci.yml @@ -16,6 +16,9 @@ issues: linters: - dupl - lll + - path: "test/*" + linters: + - lll linters: disable-all: true enable: diff --git a/infra/feast-operator/Makefile b/infra/feast-operator/Makefile index 445b98fd1a0..9dc38a2b04a 100644 --- a/infra/feast-operator/Makefile +++ b/infra/feast-operator/Makefile @@ -113,13 +113,19 @@ vet: ## Run go vet against code. .PHONY: test test: build-installer vet lint envtest ## Run tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v test/e2e | grep -v test/data-source-types) -coverprofile cover.out # Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors. .PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up. test-e2e: go test -timeout 30m ./test/e2e/ -v -ginkgo.v +# Requires python3 +.PHONY: test-datasources +test-datasources: + python3 test/data-source-types/data-source-types.py + go test ./test/data-source-types/ + .PHONY: lint lint: golangci-lint ## Run golangci-lint linter & yamllint $(GOLANGCI_LINT) run diff --git a/infra/feast-operator/api/v1alpha1/featurestore_types.go b/infra/feast-operator/api/v1alpha1/featurestore_types.go index c73806df3b6..9c25d2c1d4b 100644 --- a/infra/feast-operator/api/v1alpha1/featurestore_types.go +++ b/infra/feast-operator/api/v1alpha1/featurestore_types.go @@ -114,8 +114,8 @@ var ValidOfflineStoreFilePersistenceTypes = []string{ // OfflineStoreDBStorePersistence configures the DB store persistence for the offline store service type OfflineStoreDBStorePersistence struct { - // Type of the persistence type you want to use. Allowed values are: snowflake.offline, bigquery, redshift, spark, postgres, trino, redis, athena, mssql - // +kubebuilder:validation:Enum=snowflake.offline;bigquery;redshift;spark;postgres;trino;redis;athena;mssql + // Type of the persistence type you want to use. + // +kubebuilder:validation:Enum=snowflake.offline;bigquery;redshift;spark;postgres;trino;athena;mssql Type string `json:"type"` // Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. SecretRef corev1.LocalObjectReference `json:"secretRef"` @@ -130,7 +130,6 @@ var ValidOfflineStoreDBStorePersistenceTypes = []string{ "spark", "postgres", "trino", - "redis", "athena", "mssql", } @@ -160,7 +159,7 @@ type OnlineStoreFilePersistence struct { // OnlineStoreDBStorePersistence configures the DB store persistence for the online store service type OnlineStoreDBStorePersistence struct { - // Type of the persistence type you want to use. Allowed values are: snowflake.online, redis, ikv, datastore, dynamodb, bigtable, postgres, cassandra, mysql, hazelcast, singlestore, hbase, elasticsearch, qdrant, couchbase, milvus + // Type of the persistence type you want to use. // +kubebuilder:validation:Enum=snowflake.online;redis;ikv;datastore;dynamodb;bigtable;postgres;cassandra;mysql;hazelcast;singlestore;hbase;elasticsearch;qdrant;couchbase;milvus Type string `json:"type"` // Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. @@ -215,7 +214,7 @@ type RegistryFilePersistence struct { // RegistryDBStorePersistence configures the DB store persistence for the registry service type RegistryDBStorePersistence struct { - // Type of the persistence type you want to use. Allowed values are: sql, snowflake.registry + // Type of the persistence type you want to use. // +kubebuilder:validation:Enum=sql;snowflake.registry Type string `json:"type"` // Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. @@ -225,8 +224,8 @@ type RegistryDBStorePersistence struct { } var ValidRegistryDBStorePersistenceTypes = []string{ - "snowflake.registry", "sql", + "snowflake.registry", } // PvcConfig defines the settings for a persistent file store based on PVCs. 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 7d9385df430..dbe08d4cd52 100644 --- a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml +++ b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml @@ -170,7 +170,6 @@ spec: - spark - postgres - trino - - redis - athena - mssql type: string @@ -2083,7 +2082,6 @@ spec: - spark - postgres - trino - - redis - athena - mssql type: string diff --git a/infra/feast-operator/dist/install.yaml b/infra/feast-operator/dist/install.yaml index a57848769c5..7010ae1caea 100644 --- a/infra/feast-operator/dist/install.yaml +++ b/infra/feast-operator/dist/install.yaml @@ -178,7 +178,6 @@ spec: - spark - postgres - trino - - redis - athena - mssql type: string @@ -2091,7 +2090,6 @@ spec: - spark - postgres - trino - - redis - athena - mssql type: string diff --git a/infra/feast-operator/docs/api/markdown/ref.md b/infra/feast-operator/docs/api/markdown/ref.md index 820d9b90539..a1eaa753d21 100644 --- a/infra/feast-operator/docs/api/markdown/ref.md +++ b/infra/feast-operator/docs/api/markdown/ref.md @@ -210,7 +210,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `type` _string_ | Type of the persistence type you want to use. Allowed values are: snowflake.offline, bigquery, redshift, spark, postgres, trino, redis, athena, mssql | +| `type` _string_ | Type of the persistence type you want to use. | | `secretRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. | | `secretKeyName` _string_ | By default, the selected store "type" is used as the SecretKeyName | @@ -286,7 +286,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `type` _string_ | Type of the persistence type you want to use. Allowed values are: snowflake.online, redis, ikv, datastore, dynamodb, bigtable, postgres, cassandra, mysql, hazelcast, singlestore, hbase, elasticsearch, qdrant, couchbase, milvus | +| `type` _string_ | Type of the persistence type you want to use. | | `secretRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. | | `secretKeyName` _string_ | By default, the selected store "type" is used as the SecretKeyName | diff --git a/infra/feast-operator/test/api/featurestore_types_test.go b/infra/feast-operator/test/api/featurestore_types_test.go index 1049436fec9..12a7406e80d 100644 --- a/infra/feast-operator/test/api/featurestore_types_test.go +++ b/infra/feast-operator/test/api/featurestore_types_test.go @@ -2,6 +2,8 @@ package api import ( "context" + "fmt" + "strings" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -334,6 +336,16 @@ func registryStoreWithDBPersistenceType(dbPersistenceType string, featureStore * return fsCopy } +func quotedSlice(stringSlice []string) string { + quotedSlice := make([]string, len(stringSlice)) + + for i, str := range stringSlice { + quotedSlice[i] = fmt.Sprintf("\"%s\"", str) + } + + return strings.Join(quotedSlice, ", ") +} + const resourceName = "test-resource" const namespaceName = "default" @@ -377,7 +389,7 @@ var _ = Describe("FeatureStore API", func() { }) It("should fail when db persistence type is invalid", func() { - attemptInvalidCreationAndAsserts(ctx, onlineStoreWithDBPersistenceType("invalid", featurestore), "Unsupported value: \"invalid\": supported values: \"snowflake.online\", \"redis\", \"ikv\", \"datastore\", \"dynamodb\", \"bigtable\", \"postgres\", \"cassandra\", \"mysql\", \"hazelcast\", \"singlestore\", \"hbase\", \"elasticsearch\", \"qdrant\", \"couchbase\"") + attemptInvalidCreationAndAsserts(ctx, onlineStoreWithDBPersistenceType("invalid", featurestore), "Unsupported value: \"invalid\": supported values: "+quotedSlice(feastdevv1alpha1.ValidOnlineStoreDBStorePersistenceTypes)) }) }) @@ -388,7 +400,7 @@ var _ = Describe("FeatureStore API", func() { attemptInvalidCreationAndAsserts(ctx, offlineStoreWithUnmanagedFileType(featurestore), "Unsupported value") }) It("should fail when db persistence type is invalid", func() { - attemptInvalidCreationAndAsserts(ctx, offlineStoreWithDBPersistenceType("invalid", featurestore), "Unsupported value: \"invalid\": supported values: \"snowflake.offline\", \"bigquery\", \"redshift\", \"spark\", \"postgres\", \"trino\", \"redis\", \"athena\", \"mssql\"") + attemptInvalidCreationAndAsserts(ctx, offlineStoreWithDBPersistenceType("invalid", featurestore), "Unsupported value: \"invalid\": supported values: "+quotedSlice(feastdevv1alpha1.ValidOfflineStoreDBStorePersistenceTypes)) }) }) @@ -410,7 +422,7 @@ var _ = Describe("FeatureStore API", func() { attemptInvalidCreationAndAsserts(ctx, registryWithS3AdditionalKeywordsForGsBucket(featurestore), "Additional S3 settings are available only for S3 object store URIs") }) It("should fail when db persistence type is invalid", func() { - attemptInvalidCreationAndAsserts(ctx, registryStoreWithDBPersistenceType("invalid", featurestore), "Unsupported value: \"invalid\": supported values: \"sql\", \"snowflake.registry\"") + attemptInvalidCreationAndAsserts(ctx, registryStoreWithDBPersistenceType("invalid", featurestore), "Unsupported value: \"invalid\": supported values: "+quotedSlice(feastdevv1alpha1.ValidRegistryDBStorePersistenceTypes)) }) }) diff --git a/infra/feast-operator/test/data-source-types/data-source-types.py b/infra/feast-operator/test/data-source-types/data-source-types.py new file mode 100644 index 00000000000..be7d70e5ede --- /dev/null +++ b/infra/feast-operator/test/data-source-types/data-source-types.py @@ -0,0 +1,18 @@ +import os +from feast.repo_config import REGISTRY_CLASS_FOR_TYPE, OFFLINE_STORE_CLASS_FOR_TYPE, ONLINE_STORE_CLASS_FOR_TYPE, LEGACY_ONLINE_STORE_CLASS_FOR_TYPE + +def save_in_script_directory(filename: str, typedict: dict[str, str]): + script_dir = os.path.dirname(os.path.abspath(__file__)) + file_path = os.path.join(script_dir, filename) + + with open(file_path, 'w') as file: + for k in typedict.keys(): + file.write(k+"\n") + +for legacyType in LEGACY_ONLINE_STORE_CLASS_FOR_TYPE.keys(): + if legacyType in ONLINE_STORE_CLASS_FOR_TYPE: + del ONLINE_STORE_CLASS_FOR_TYPE[legacyType] + +save_in_script_directory("registry.out", REGISTRY_CLASS_FOR_TYPE) +save_in_script_directory("online-store.out", ONLINE_STORE_CLASS_FOR_TYPE) +save_in_script_directory("offline-store.out", OFFLINE_STORE_CLASS_FOR_TYPE) diff --git a/infra/feast-operator/test/data-source-types/data_source_types_test.go b/infra/feast-operator/test/data-source-types/data_source_types_test.go new file mode 100644 index 00000000000..8448b2c4212 --- /dev/null +++ b/infra/feast-operator/test/data-source-types/data_source_types_test.go @@ -0,0 +1,88 @@ +package datasources + +import ( + "bufio" + "os" + "slices" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + feastdevv1alpha1 "github.com/feast-dev/feast/infra/feast-operator/api/v1alpha1" + "github.com/feast-dev/feast/infra/feast-operator/internal/controller/services" +) + +func TestDataSourceTypes(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Data Source Suite") +} + +var _ = Describe("FeatureStore Data Source Types", func() { + Context("When checking against the python code in feast.repo_config", func() { + It("should match defined registry persistence types in the operator", func() { + registryFilePersistenceTypes := []string{string(services.RegistryFileConfigType)} + registryPersistenceTypes := append(feastdevv1alpha1.ValidRegistryDBStorePersistenceTypes, registryFilePersistenceTypes...) + checkPythonPersistenceTypes("registry.out", registryPersistenceTypes) + }) + It("should match defined onlineStore persistence types in the operator", func() { + onlineFilePersistenceTypes := []string{string(services.OnlineSqliteConfigType)} + onlinePersistenceTypes := append(feastdevv1alpha1.ValidOnlineStoreDBStorePersistenceTypes, onlineFilePersistenceTypes...) + checkPythonPersistenceTypes("online-store.out", onlinePersistenceTypes) + }) + It("should match defined offlineStore persistence types in the operator", func() { + offlinePersistenceTypes := append(feastdevv1alpha1.ValidOfflineStoreDBStorePersistenceTypes, feastdevv1alpha1.ValidOfflineStoreFilePersistenceTypes...) + checkPythonPersistenceTypes("offline-store.out", offlinePersistenceTypes) + }) + }) +}) + +func checkPythonPersistenceTypes(fileName string, operatorDsTypes []string) { + feastDsTypes, err := readFileLines(fileName) + Expect(err).NotTo(HaveOccurred()) + + // Add remote type to slice, as its not a file or db type and we want to limit its use to registry service when deploying with the operator + operatorDsTypes = append(operatorDsTypes, "remote") + missingFeastTypes := []string{} + for _, ods := range operatorDsTypes { + if len(ods) > 0 { + if !slices.Contains(feastDsTypes, ods) { + missingFeastTypes = append(missingFeastTypes, ods) + } + } + } + Expect(missingFeastTypes).To(BeEmpty()) + + missingOperatorTypes := []string{} + for _, fds := range feastDsTypes { + if len(fds) > 0 { + if !slices.Contains(operatorDsTypes, fds) { + missingOperatorTypes = append(missingOperatorTypes, fds) + } + } + } + Expect(missingOperatorTypes).To(BeEmpty()) +} + +func readFileLines(filePath string) ([]string, error) { + file, err := os.Open(filePath) + Expect(err).NotTo(HaveOccurred()) + defer closeFile(file) + + var lines []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + + err = scanner.Err() + Expect(err).NotTo(HaveOccurred()) + + return lines, nil +} + +func closeFile(file *os.File) { + err := file.Close() + Expect(err).NotTo(HaveOccurred()) +} From 46f8d7aa87cfaf36d17c162c4f41cd983a2938d5 Mon Sep 17 00:00:00 2001 From: Tom Steenbergen <41334387+TomSteenbergen@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:58:28 +0100 Subject: [PATCH 19/30] fix: Ensure Postgres queries are committed or autocommit is used (#5039) --- .../postgres_online_store/postgres.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sdk/python/feast/infra/online_stores/postgres_online_store/postgres.py b/sdk/python/feast/infra/online_stores/postgres_online_store/postgres.py index f43247a5457..4f519003d61 100644 --- a/sdk/python/feast/infra/online_stores/postgres_online_store/postgres.py +++ b/sdk/python/feast/infra/online_stores/postgres_online_store/postgres.py @@ -58,7 +58,9 @@ class PostgreSQLOnlineStore(OnlineStore): _conn_pool_async: Optional[AsyncConnectionPool] = None @contextlib.contextmanager - def _get_conn(self, config: RepoConfig) -> Generator[Connection, Any, Any]: + def _get_conn( + self, config: RepoConfig, autocommit: bool = False + ) -> Generator[Connection, Any, Any]: assert config.online_store.type == "postgres" if config.online_store.conn_type == ConnectionType.pool: @@ -66,16 +68,18 @@ def _get_conn(self, config: RepoConfig) -> Generator[Connection, Any, Any]: self._conn_pool = _get_connection_pool(config.online_store) self._conn_pool.open() connection = self._conn_pool.getconn() + connection.set_autocommit(autocommit) yield connection self._conn_pool.putconn(connection) else: if not self._conn: self._conn = _get_conn(config.online_store) + self._conn.set_autocommit(autocommit) yield self._conn @contextlib.asynccontextmanager async def _get_conn_async( - self, config: RepoConfig + self, config: RepoConfig, autocommit: bool = False ) -> AsyncGenerator[AsyncConnection, Any]: if config.online_store.conn_type == ConnectionType.pool: if not self._conn_pool_async: @@ -84,11 +88,13 @@ async def _get_conn_async( ) await self._conn_pool_async.open() connection = await self._conn_pool_async.getconn() + await connection.set_autocommit(autocommit) yield connection await self._conn_pool_async.putconn(connection) else: if not self._conn_async: self._conn_async = await _get_conn_async(config.online_store) + await self._conn_async.set_autocommit(autocommit) yield self._conn_async def online_write_batch( @@ -161,7 +167,7 @@ def online_read( config, table, keys, requested_features ) - with self._get_conn(config) as conn, conn.cursor() as cur: + with self._get_conn(config, autocommit=True) as conn, conn.cursor() as cur: cur.execute(query, params) rows = cur.fetchall() @@ -179,7 +185,7 @@ async def online_read_async( config, table, keys, requested_features ) - async with self._get_conn_async(config) as conn: + async with self._get_conn_async(config, autocommit=True) as conn: async with conn.cursor() as cur: await cur.execute(query, params) rows = await cur.fetchall() @@ -339,6 +345,7 @@ def teardown( for table in tables: table_name = _table_id(project, table) cur.execute(_drop_table_and_index(table_name)) + conn.commit() except Exception: logging.exception("Teardown failed") raise @@ -398,7 +405,7 @@ def retrieve_online_documents( Optional[ValueProto], ] ] = [] - with self._get_conn(config) as conn, conn.cursor() as cur: + with self._get_conn(config, autocommit=True) as conn, conn.cursor() as cur: table_name = _table_id(project, table) # Search query template to find the top k items that are closest to the given embedding From e14751abfe658c2ea17e60846f7abbf3a47656f1 Mon Sep 17 00:00:00 2001 From: Tom Steenbergen <41334387+TomSteenbergen@users.noreply.github.com> Date: Tue, 11 Feb 2025 14:03:56 +0100 Subject: [PATCH 20/30] chore: Update adopters list (#5042) * Update adopters list Signed-off-by: TomSteenbergen * Format table Signed-off-by: TomSteenbergen --------- Signed-off-by: TomSteenbergen --- community/ADOPTERS.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/community/ADOPTERS.md b/community/ADOPTERS.md index 5ef285b41b8..38da2012efe 100644 --- a/community/ADOPTERS.md +++ b/community/ADOPTERS.md @@ -4,13 +4,14 @@ Below are the adopters of Feast. If you are using Feast please add yourself into the following list by a pull request. Please keep the list in alphabetical order. -| Organization | Contact | GitHub Username | -| ------------ | ------- | ------- | -| Affirm | Francisco Javier Arceo | franciscojavierarceo | -| Bank of Georgia | Tornike Gurgenidze | tokoko | -| Get Ground | Zhiling Chen | zhilingc | -| Gojek | Pradithya Aria Pura | pradithya | -| Twitter | David Liu | mavysavydav| -| SeatGeek | Rob Howley | robhowley | -| Shopify | Matt Delacour | MattDelac | -| Snowflake | Miles Adkins | sfc-gh-madkins | +| Organization | Contact | GitHub Username | +|-----------------|------------------------|----------------------| +| Affirm | Francisco Javier Arceo | franciscojavierarceo | +| Bank of Georgia | Tornike Gurgenidze | tokoko | +| Get Ground | Zhiling Chen | zhilingc | +| Gojek | Pradithya Aria Pura | pradithya | +| Picnic | Tom Steenbergen | TomSteenbergen | +| Twitter | David Liu | mavysavydav | +| SeatGeek | Rob Howley | robhowley | +| Shopify | Matt Delacour | MattDelac | +| Snowflake | Miles Adkins | sfc-gh-madkins | From ae68e4de0c184dc2990ea7e8d08d2d7f1613b06f Mon Sep 17 00:00:00 2001 From: Shaktidhar Kanamarla <108393456+ShaktidharK1997@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:12:43 -0500 Subject: [PATCH 21/30] feat: Adding Click command to display configuration details (#5036) * Adding Click command to display configuration details Signed-off-by: ShaktidharK1997 * Adding unit test for configuration CLI command and documentation for the same Signed-off-by: ShaktidharK1997 --------- Signed-off-by: ShaktidharK1997 --- docs/reference/feast-cli-commands.md | 23 +++++++++++++++++++++++ sdk/python/feast/cli.py | 18 ++++++++++++++++++ sdk/python/tests/unit/cli/test_cli.py | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/docs/reference/feast-cli-commands.md b/docs/reference/feast-cli-commands.md index 8f1a7c302e6..712df18a6b6 100644 --- a/docs/reference/feast-cli-commands.md +++ b/docs/reference/feast-cli-commands.md @@ -19,6 +19,7 @@ Options: Commands: apply Create or update a feature store deployment + configuration Display Feast configuration entities Access entities feature-views Access feature views init Create a new Feast repository @@ -61,6 +62,28 @@ feast apply `feast apply` \(when configured to use cloud provider like `gcp` or `aws`\) will create cloud infrastructure. This may incur costs. {% endhint %} +## Configuration + +Display the actual configuration being used by Feast, including both user-provided configurations and default configurations applied by Feast. + +```bash +feast configuration +``` + +```yaml +project: foo +registry: data/registry.db +provider: local +online_store: + type: sqlite + path: data/online_store.db +offline_store: + type: dask +entity_key_serialization_version: 2 +auth: + type: no_auth +``` + ## Entities List all registered entities diff --git a/sdk/python/feast/cli.py b/sdk/python/feast/cli.py index 165677a843a..890c79aa856 100644 --- a/sdk/python/feast/cli.py +++ b/sdk/python/feast/cli.py @@ -137,6 +137,24 @@ def version(): print(f'Feast SDK Version: "{importlib_version("feast")}"') +@cli.command() +@click.pass_context +def configuration(ctx: click.Context): + """ + Display Feast configuration + """ + repo = ctx.obj["CHDIR"] + fs_yaml_file = ctx.obj["FS_YAML_FILE"] + cli_check_repo(repo, fs_yaml_file) + repo_config = load_repo_config(repo, fs_yaml_file) + if repo_config: + config_dict = repo_config.model_dump(by_alias=True, exclude_unset=True) + config_dict.pop("repo_path", None) + print(yaml.dump(config_dict, default_flow_style=False, sort_keys=False)) + else: + print("No configuration found.") + + @cli.command() @click.option( "--host", diff --git a/sdk/python/tests/unit/cli/test_cli.py b/sdk/python/tests/unit/cli/test_cli.py index a286c847dd2..b09eabebb80 100644 --- a/sdk/python/tests/unit/cli/test_cli.py +++ b/sdk/python/tests/unit/cli/test_cli.py @@ -170,3 +170,23 @@ def setup_third_party_registry_store_repo( ) yield repo_path + + +def test_cli_configuration(): + """ + Unit test for the 'feast configuration' command + """ + runner = CliRunner() + + with setup_third_party_provider_repo("local") as repo_path: + # Run the 'feast configuration' command + return_code, output = runner.run_with_output(["configuration"], cwd=repo_path) + + # Assertions + assertpy.assert_that(return_code).is_equal_to(0) + assertpy.assert_that(output).contains(b"project: foo") + assertpy.assert_that(output).contains(b"provider: local") + assertpy.assert_that(output).contains(b"type: sqlite") + assertpy.assert_that(output).contains(b"path: data/online_store.db") + assertpy.assert_that(output).contains(b"type: file") + assertpy.assert_that(output).contains(b"entity_key_serialization_version: 2") From 8551714fa323fb2615cb457194dc551550107b1b Mon Sep 17 00:00:00 2001 From: Tommy Hughes IV Date: Wed, 12 Feb 2025 11:11:54 -0600 Subject: [PATCH 22/30] chore: Operator - increase maxDescLen to include some CRD descriptions (#5045) increase maxDescLen to include some CRD descriptions Signed-off-by: Tommy Hughes --- infra/feast-operator/Makefile | 2 +- .../crd/bases/feast.dev_featurestores.yaml | 2692 +++++++++++++++++ infra/feast-operator/dist/install.yaml | 2692 +++++++++++++++++ 3 files changed, 5385 insertions(+), 1 deletion(-) diff --git a/infra/feast-operator/Makefile b/infra/feast-operator/Makefile index 9dc38a2b04a..223053d0a8f 100644 --- a/infra/feast-operator/Makefile +++ b/infra/feast-operator/Makefile @@ -97,7 +97,7 @@ help: ## Display this help. .PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) rbac:roleName=manager-role crd:maxDescLen=0 webhook paths="./..." output:crd:artifacts:config=config/crd/bases + $(CONTROLLER_GEN) rbac:roleName=manager-role crd:maxDescLen=120 webhook paths="./..." output:crd:artifacts:config=config/crd/bases .PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. 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 dbe08d4cd52..324411eb877 100644 --- a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml +++ b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml @@ -26,30 +26,53 @@ spec: name: v1alpha1 schema: openAPIV3Schema: + description: FeatureStore is the Schema for the featurestores API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: FeatureStoreSpec defines the desired state of FeatureStore properties: authz: + description: AuthzConfig defines the authorization settings for the + deployed Feast services. properties: kubernetes: + description: |- + KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. + https://kubernetes. properties: roles: + description: The Kubernetes RBAC roles to be deployed in the + same namespace of the FeatureStore. items: type: string type: array type: object oidc: + description: |- + OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. + https://auth0. properties: secretRef: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -61,45 +84,74 @@ spec: - message: One selection required between kubernetes or oidc. rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' feastProject: + description: FeastProject is the Feast project id. pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ type: string services: + description: FeatureStoreServices defines the desired feast services. + An ephemeral registry is deployed by default. properties: deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. properties: rollingUpdate: + description: |- + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. properties: maxSurge: anyOf: - type: integer - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string + description: The maximum number of pods that can be unavailable + during the update. x-kubernetes-int-or-string: true type: object type: + description: Type of deployment. Can be "Recreate" or "RollingUpdate". + Default is RollingUpdate. type: string type: object disableInitContainers: + description: Disable the 'feast repo initialization' initContainer type: boolean offlineStore: + description: OfflineStore configures the deployed offline store + service properties: persistence: + description: OfflineStorePersistence configures the persistence + settings for the offline store service properties: file: + description: OfflineStoreFilePersistence configures the + file-based persistence for the offline store service properties: pvc: + description: PvcConfig defines the settings for a + persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent volume + access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -108,6 +160,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -116,20 +171,33 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which this + persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -152,17 +220,30 @@ spec: type: string type: object store: + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the secret + key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you want + to use. enum: - snowflake.offline - bigquery @@ -182,63 +263,108 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a remote offline server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -251,24 +377,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of + a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must + be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -277,8 +421,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -287,11 +436,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -307,6 +466,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -315,23 +477,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -341,21 +520,43 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of a Volume + within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. type: string required: - mountPath @@ -365,22 +566,35 @@ spec: type: object type: object onlineStore: + description: OnlineStore configures the deployed online store + service properties: persistence: + description: OnlineStorePersistence configures the persistence + settings for the online store service properties: file: + description: OnlineStoreFilePersistence configures the + file-based persistence for the online store service properties: path: type: string pvc: + description: PvcConfig defines the settings for a + persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent volume + access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -389,6 +603,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -397,20 +614,33 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which this + persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -438,17 +668,30 @@ spec: rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) : true' store: + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the secret + key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you want + to use. enum: - snowflake.online - redis @@ -476,63 +719,108 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a feature server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -545,24 +833,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of + a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must + be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -571,8 +877,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -581,11 +892,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -601,6 +922,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -609,23 +933,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -635,21 +976,43 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of a Volume + within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. type: string required: - mountPath @@ -659,24 +1022,39 @@ spec: type: object type: object registry: + description: Registry configures the registry service. One selection + is required. Local is the default setting. properties: local: + description: LocalRegistryConfig configures the deployed registry + service properties: persistence: + description: RegistryPersistence configures the persistence + settings for the registry service properties: file: + description: RegistryFilePersistence configures the + file-based persistence for the registry service properties: path: type: string pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -685,6 +1063,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -693,20 +1074,34 @@ spec: - 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 + description: Requests describes the + minimum amount of compute resources + required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -746,17 +1141,30 @@ spec: rule: '(has(self.s3_additional_kwargs) && has(self.path)) ? self.path.startsWith(''s3://'') : true' store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you + want to use. enum: - sql - snowflake.registry @@ -771,63 +1179,111 @@ spec: rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a registry server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' properties: apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required + for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to + select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in + the pod's namespace properties: key: + description: The key of the secret to + select from. Must be a valid secret + key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -840,24 +1296,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source + of a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + must be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -866,8 +1340,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -876,11 +1355,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -896,6 +1385,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -904,23 +1396,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for + a feast service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -930,21 +1439,44 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of + a Volume within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. type: string required: - mountPath @@ -954,26 +1486,44 @@ spec: type: object type: object remote: + description: RemoteRegistryConfig points to a remote feast + registry server. properties: feastRef: + description: Reference to an existing `FeatureStore` CR + in the same k8s cluster. properties: name: + description: Name of the FeatureStore type: string namespace: + description: Namespace of the FeatureStore type: string required: - name type: object hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` type: string tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. properties: certName: + description: defines the configmap key name for the + client TLS cert. type: string configMapRef: + description: references the local k8s configmap where + the TLS cert resides properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -991,63 +1541,107 @@ spec: - message: One selection required. rule: '[has(self.local), has(self.remote)].exists_one(c, c)' ui: + description: Creates a UI server container properties: env: items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -1060,24 +1654,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of a set + of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to each + key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must be + defined type: boolean type: object x-kubernetes-map-type: atomic @@ -1086,8 +1698,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when to + pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -1096,11 +1713,20 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute resource + requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -1116,6 +1742,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1124,23 +1753,40 @@ spec: - 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 + description: Requests describes the minimum amount of + compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. useful + in an openshift cluster, for example, where TLS is configured + by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key names + for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where the + TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -1150,21 +1796,43 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes that + should be mounted into the feast container. items: + description: VolumeMount describes a mounting of a Volume + within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. type: string required: - mountPath @@ -1173,109 +1841,209 @@ spec: type: array type: object volumes: + description: Volumes specifies the volumes to mount in the FeatureStore + deployment. items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. properties: awsElasticBlockStore: + description: |- + awsElasticBlockStore represents an AWS Disk resource that is attached to a + kubelet's host machine and then exposed to th properties: fsType: + description: fsType is the filesystem type of the volume + that you want to mount. type: string partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. format: int32 type: integer readOnly: + description: |- + readOnly value true will force the readOnly setting in VolumeMounts. + More info: https://kubernetes. type: boolean volumeID: + description: |- + volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). + More info: https://kubernetes. type: string required: - volumeID type: object azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. properties: cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: + description: diskName is the Name of the data disk in + the blob storage type: string diskURI: + description: diskURI is the URI of data disk in the + blob storage type: string fsType: + description: |- + fsType is Filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage accoun' type: string readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. properties: readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime properties: monitors: + description: |- + monitors is Required: Monitors is a collection of Ceph monitors + More info: https://examples.k8s. items: type: string type: array x-kubernetes-list-type: atomic path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default is /' type: string readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretFile: + description: 'secretFile is Optional: SecretFile is + the path to key ring for User, default is /etc/ceph/user.' type: string secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is + empty.' properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic user: + description: |- + user is optional: User is the rados user name, default is admin + More info: https://examples.k8s. type: string required: - monitors type: object cinder: + description: |- + cinder represents a cinder volume attached and mounted on kubelets host machine. + More info: https://examples.k8s. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef is optional: points to a secret object containing parameters used to connect + to OpenStack. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic volumeID: + description: |- + volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md type: string required: - volumeID type: object configMap: + description: configMap represents a configMap that should + populate this volume properties: defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default.' format: int32 type: integer items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum items: + description: Maps a string key to a path within a + volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode bits used + to set permissions on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -1285,67 +2053,121 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object x-kubernetes-map-type: atomic csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta fea properties: driver: + description: driver is the name of the CSI driver that + handles this volume. type: string fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". type: string nodePublishSecretRef: + description: |- + nodePublishSecretRef is a reference to the secret object containing + sensitive information to pass to the CSI driver to c properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic readOnly: + description: |- + readOnly specifies a read-only configuration for the volume. + Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string + description: |- + volumeAttributes stores driver-specific properties that are passed to the CSI + driver. type: object required: - driver type: object downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume properties: defaultMode: + description: 'Optional: mode bits to use on created + files by default.' format: int32 type: integer items: + description: Items is a list of downward API volume + file items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field properties: fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name, namespace + and uid are supported.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu format: int32 type: integer path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path.' type: string resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource @@ -1358,36 +2180,63 @@ spec: x-kubernetes-list-type: atomic type: object emptyDir: + description: |- + emptyDir represents a temporary directory that shares a pod's lifetime. + More info: https://kubernetes. properties: medium: + description: medium represents what type of storage + medium should back this directory. type: string sizeLimit: anyOf: - type: integer - type: string + description: sizeLimit is the total amount of local + storage required for this EmptyDir volume. 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 ephemeral: + description: ephemeral represents a volume that is handled + by a cluster storage driver. properties: volumeClaimTemplate: + description: Will be used to create a stand-alone PVC + to provision the volume. properties: metadata: + description: |- + May contain labels and annotations that will be copied into the PVC + when creating it. type: object spec: + description: The specification for the PersistentVolumeClaim. properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s. properties: apiGroup: + description: APIGroup is the group for the + resource being referenced. type: string kind: + description: Kind is the type of resource + being referenced type: string name: + description: Name is the name of resource + being referenced type: string required: - kind @@ -1395,20 +2244,34 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. properties: apiGroup: + description: APIGroup is the group for the + resource being referenced. type: string kind: + description: Kind is the type of resource + being referenced type: string name: + description: Name is the name of resource + being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking. type: string required: - kind - name type: object resources: + description: resources represents the minimum + resources the volume should have. properties: limits: additionalProperties: @@ -1417,6 +2280,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1425,18 +2291,36 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object selector: + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: + description: key is the label key + that the selector applies to. type: string operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -1450,16 +2334,28 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes. type: string volumeAttributesClassName: + description: volumeAttributesClassName may be + used to set the VolumeAttributesClass used + by this claim. type: string volumeMode: + description: volumeMode defines what type of + volume is required by the claim. type: string volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. type: string type: object required: @@ -1467,41 +2363,78 @@ spec: type: object type: object fc: + description: fc represents a Fibre Channel resource that + is attached to a kubelet's host machine and then exposed + to the pod. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string lun: + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' items: type: string type: array x-kubernetes-list-type: atomic wwids: + description: "wwids Optional: FC volume world wide identifiers + (wwids)\nEither wwids or combination of targetWWNs + and lun must be set, " items: type: string type: array x-kubernetes-list-type: atomic type: object flexVolume: + description: |- + flexVolume represents a generic volume resource that is + provisioned/attached using an exec based plugin. properties: driver: + description: driver is the name of the driver to use + for this volume. type: string fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string options: additionalProperties: type: string + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: + description: |- + readOnly is Optional: defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef is Optional: secretRef is reference to the secret object containing + sensitive information to pass to the plugi properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -1509,90 +2442,170 @@ spec: - driver type: object flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. properties: datasetName: + description: |- + datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker + should be considered as depreca type: string datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: + description: |- + gcePersistentDisk represents a GCE Disk resource that is attached to a + kubelet's host machine and then exposed to the po properties: fsType: + description: fsType is filesystem type of the volume + that you want to mount. type: string partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. format: int32 type: integer pdName: + description: |- + pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. + More info: https://kubernetes. type: string readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://kubernetes. type: boolean required: - pdName type: object gitRepo: + description: |- + gitRepo represents a git repository at a particular revision. + DEPRECATED: GitRepo is deprecated. properties: directory: + description: |- + directory is the target directory name. + Must not contain or start with '..'. If '. type: string repository: + description: repository is the URL type: string revision: + description: revision is the commit hash for the specified + revision. type: string required: - repository type: object glusterfs: + description: |- + glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. properties: endpoints: + description: |- + endpoints is the endpoint name that details Glusterfs topology. + More info: https://examples.k8s. type: string path: + description: |- + path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod type: string readOnly: + description: |- + readOnly here will force the Glusterfs volume to be mounted with read-only permissions. + Defaults to false. type: boolean required: - endpoints - path type: object hostPath: + description: |- + hostPath represents a pre-existing file or directory on the host + machine that is directly exposed to the container. properties: path: + description: |- + path of the directory on the host. + If the path is a symlink, it will follow the link to the real path. type: string type: + description: |- + type for HostPath Volume + Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath type: string required: - path type: object iscsi: + description: |- + iscsi represents an ISCSI Disk resource that is attached to a + kubelet's host machine and then exposed to the pod. properties: chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: + description: fsType is the filesystem type of the volume + that you want to mount. type: string initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. type: string iqn: + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + description: |- + iscsiInterface is the interface Name that uses an iSCSI transport. + Defaults to 'default' (tcp). type: string lun: + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: + description: portals is the iSCSI Target Portal List. items: type: string type: array x-kubernetes-list-type: atomic readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. type: boolean secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic targetPortal: + description: targetPortal is iSCSI Target Portal. type: string required: - iqn @@ -1600,68 +2613,138 @@ spec: - targetPortal type: object name: + description: |- + name of the volume. + Must be a DNS_LABEL and unique within the pod. + More info: https://kubernetes. type: string nfs: + description: |- + nfs represents an NFS mount on the host that shares a pod's lifetime + More info: https://kubernetes. properties: path: + description: |- + path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs type: string readOnly: + description: |- + readOnly here will force the NFS export to be mounted with read-only permissions. + Defaults to false. type: boolean server: + description: |- + server is the hostname or IP address of the NFS server. + More info: https://kubernetes. type: string required: - path - server type: object persistentVolumeClaim: + description: |- + persistentVolumeClaimVolumeSource represents a reference to a + PersistentVolumeClaim in the same namespace. properties: claimName: + description: claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. type: string readOnly: + description: |- + readOnly Will force the ReadOnly setting in VolumeMounts. + Default false. type: boolean required: - claimName type: object photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk type: string required: - pdID type: object portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine properties: fsType: + description: |- + fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating system. + Ex. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean volumeID: + description: volumeID uniquely identifies a Portworx + volume type: string required: - volumeID type: object projected: + description: projected items for all in one resources secrets, + configmaps, and downward API properties: defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. format: int32 type: integer sources: + description: sources is the list of volume projections items: + description: Projection that may be projected along + with other supported volume types properties: clusterTrustBundle: + description: ClusterTrustBundle allows a pod to + access the `.spec. properties: labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. properties: matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: + description: key is the label key + that the selector applies to. type: string operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -1675,31 +2758,58 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. type: string optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. type: boolean path: + description: Relative path from the volume + root to write the bundle. type: string signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. type: string required: - path type: object configMap: + description: configMap information about the configMap + data to project properties: items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum items: + description: Maps a string key to a path + within a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -1709,42 +2819,81 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional specify whether the + ConfigMap or its keys must be defined type: boolean type: object x-kubernetes-map-type: atomic downwardAPI: + description: downwardAPI information about the + downwardAPI data to project properties: items: + description: Items is a list of DownwardAPIVolume + file items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field properties: fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name, namespace and uid are supported.' properties: apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". type: string fieldPath: + description: Path of the field to + select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu format: int32 type: integer path: + description: 'Required: Path is the + relative path name of the file to + be created. Must not be absolute or + contain the ''..'' path.' type: string resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. properties: containerName: + description: 'Container name: required + for volumes, optional for env + vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource + to select' type: string required: - resource @@ -1757,16 +2906,30 @@ spec: x-kubernetes-list-type: atomic type: object secret: + description: secret information about the secret + data to project properties: items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a items: + description: Maps a string key to a path + within a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -1776,19 +2939,35 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object x-kubernetes-map-type: atomic serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: + description: audience is the intended audience + of the token. type: string expirationSeconds: + description: |- + expirationSeconds is the requested duration of validity of the service + account token. format: int64 type: integer path: + description: |- + path is the path relative to the mount point of the file to project the + token into. type: string required: - path @@ -1798,79 +2977,164 @@ spec: x-kubernetes-list-type: atomic type: object quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime properties: group: + description: |- + group to map volume access to + Default is no group type: string readOnly: + description: |- + readOnly here will force the Quobyte volume to be mounted with read-only permissions. + Defaults to false. type: boolean registry: + description: |- + registry represents a single or multiple Quobyte Registry services + specified as a string as host:port pair (multiple ent type: string tenant: + description: |- + tenant owning the given Quobyte volume in the Backend + Used with dynamically provisioned Quobyte volumes, value is set by type: string user: + description: |- + user to map volume access to + Defaults to serivceaccount user type: string volume: + description: volume is a string that references an already + created Quobyte volume by name. type: string required: - registry - volume type: object rbd: + description: |- + rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. properties: fsType: + description: fsType is the filesystem type of the volume + that you want to mount. type: string image: + description: |- + image is the rados image name. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + description: |- + keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. + More info: https://examples.k8s. type: string monitors: + description: |- + monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it items: type: string type: array x-kubernetes-list-type: atomic pool: + description: |- + pool is the rados pool name. + Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://examples.k8s. type: boolean secretRef: + description: |- + secretRef is name of the authentication secret for RBDUser. If provided + overrides keyring. + Default is nil. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic user: + description: |- + user is the rados user name. + Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string required: - image - monitors type: object scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string gateway: + description: gateway is the host address of the ScaleIO + API Gateway. type: string protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. type: string readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef references to the secret for ScaleIO user and other + sensitive information. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false type: boolean storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. type: string storagePool: + description: storagePool is the ScaleIO Storage Pool + associated with the protection domain. type: string system: + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: + description: |- + volumeName is the name of a volume already created in the ScaleIO system + that is associated with this volume source. type: string required: - gateway @@ -1878,19 +3142,35 @@ spec: - system type: object secret: + description: |- + secret represents a secret that should populate this volume. + More info: https://kubernetes. properties: defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default.' format: int32 type: integer items: + description: |- + items If unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a items: + description: Maps a string key to a path within a + volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode bits used + to set permissions on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -1899,37 +3179,75 @@ spec: type: array x-kubernetes-list-type: atomic optional: + description: optional field specify whether the Secret + or its keys must be defined type: boolean secretName: + description: |- + secretName is the name of the secret in the pod's namespace to use. + More info: https://kubernetes. type: string type: object storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef specifies the secret to use for obtaining the StorageOS API + credentials. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic volumeName: + description: |- + volumeName is the human-readable name of the StorageOS volume. Volume + names are only unique within a namespace. type: string volumeNamespace: + description: volumeNamespace specifies the scope of + the volume within StorageOS. type: string type: object vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine properties: fsType: + description: |- + fsType is filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. type: string storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath @@ -1943,24 +3261,44 @@ spec: - feastProject type: object status: + description: FeatureStoreStatus defines the observed state of FeatureStore properties: applied: + description: Shows the currently applied feast configuration, including + any pertinent defaults properties: authz: + description: AuthzConfig defines the authorization settings for + the deployed Feast services. properties: kubernetes: + description: |- + KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. + https://kubernetes. properties: roles: + description: The Kubernetes RBAC roles to be deployed + in the same namespace of the FeatureStore. items: type: string type: array type: object oidc: + description: |- + OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. + https://auth0. properties: secretRef: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -1973,45 +3311,75 @@ spec: rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' feastProject: + description: FeastProject is the Feast project id. pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ type: string services: + description: FeatureStoreServices defines the desired feast services. + An ephemeral registry is deployed by default. properties: deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. properties: rollingUpdate: + description: |- + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. properties: maxSurge: anyOf: - type: integer - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string + description: The maximum number of pods that can be + unavailable during the update. x-kubernetes-int-or-string: true type: object type: + description: Type of deployment. Can be "Recreate" or + "RollingUpdate". Default is RollingUpdate. type: string type: object disableInitContainers: + description: Disable the 'feast repo initialization' initContainer type: boolean offlineStore: + description: OfflineStore configures the deployed offline + store service properties: persistence: + description: OfflineStorePersistence configures the persistence + settings for the offline store service properties: file: + description: OfflineStoreFilePersistence configures + the file-based persistence for the offline store + service properties: pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -2020,6 +3388,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2028,20 +3399,34 @@ spec: - 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 + description: Requests describes the + minimum amount of compute resources + required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2064,17 +3449,30 @@ spec: type: string type: object store: + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you + want to use. enum: - snowflake.offline - bigquery @@ -2095,63 +3493,111 @@ spec: rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a remote offline server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' properties: apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required + for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to + select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in + the pod's namespace properties: key: + description: The key of the secret to + select from. Must be a valid secret + key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -2164,24 +3610,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source + of a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + must be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -2190,8 +3654,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -2200,11 +3669,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -2220,6 +3699,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2228,23 +3710,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for + a feast service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2254,21 +3753,44 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of + a Volume within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. type: string required: - mountPath @@ -2278,22 +3800,36 @@ spec: type: object type: object onlineStore: + description: OnlineStore configures the deployed online store + service properties: persistence: + description: OnlineStorePersistence configures the persistence + settings for the online store service properties: file: + description: OnlineStoreFilePersistence configures + the file-based persistence for the online store + service properties: path: type: string pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -2302,6 +3838,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2310,20 +3849,34 @@ spec: - 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 + description: Requests describes the + minimum amount of compute resources + required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2352,17 +3905,30 @@ spec: rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) : true' store: + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you + want to use. enum: - snowflake.online - redis @@ -2391,63 +3957,111 @@ spec: rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a feature server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' properties: apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required + for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to + select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in + the pod's namespace properties: key: + description: The key of the secret to + select from. Must be a valid secret + key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -2460,24 +4074,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source + of a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + must be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -2486,8 +4118,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -2496,11 +4133,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -2516,6 +4163,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2524,23 +4174,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for + a feast service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2550,21 +4217,44 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of + a Volume within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. type: string required: - mountPath @@ -2574,24 +4264,43 @@ spec: type: object type: object registry: + description: Registry configures the registry service. One + selection is required. Local is the default setting. properties: local: + description: LocalRegistryConfig configures the deployed + registry service properties: persistence: + description: RegistryPersistence configures the persistence + settings for the registry service properties: file: + description: RegistryFilePersistence configures + the file-based persistence for the registry + service properties: path: type: string pvc: + description: PvcConfig defines the settings + for a persistent file store based on PVCs. properties: create: + description: Settings for creating a new + PVC properties: accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to + ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the + storage resource requirements for + a volume. properties: limits: additionalProperties: @@ -2600,6 +4309,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2608,20 +4320,36 @@ spec: - 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 + description: Requests describes + the minimum amount of compute + resources required. type: object type: object storageClassName: + description: StorageClassName is the + name of an existing StorageClass + to which this persistent volume + belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing + field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2661,17 +4389,30 @@ spec: rule: '(has(self.s3_additional_kwargs) && has(self.path)) ? self.path.startsWith(''s3://'') : true' store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service properties: secretKeyName: + description: By default, the selected store + "type" is used as the SecretKeyName type: string secretRef: + description: Data store parameters should + be placed as-is from the "feature_store.yaml" + under the secret key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type + you want to use. enum: - sql - snowflake.registry @@ -2687,63 +4428,113 @@ spec: rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a registry server container properties: env: items: + description: EnvVar represents an environment + variable present in a Container. properties: name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the + ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the + pod: supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' properties: apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". type: string fieldPath: + description: Path of the field to + select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required + for volumes, optional for env + vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource + to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret + in the pod's namespace properties: key: + description: The key of the secret + to select from. Must be a valid + secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the + Secret or its key must be defined type: boolean required: - key @@ -2756,24 +4547,43 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source + of a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be + a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + must be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -2782,8 +4592,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for + if/when to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -2792,11 +4607,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the + compute resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -2812,6 +4637,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2820,23 +4648,41 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS + for a feast service. properties: disable: + description: will disable TLS for the feast + service. useful in an openshift cluster, + for example, where TLS is configured by + default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret + where the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2847,21 +4693,46 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of + volumes that should be mounted into the feast + container. items: + description: VolumeMount describes a mounting + of a Volume within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of + a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume + from which the container's volume should + be mounted. type: string required: - mountPath @@ -2871,26 +4742,44 @@ spec: type: object type: object remote: + description: RemoteRegistryConfig points to a remote feast + registry server. properties: feastRef: + description: Reference to an existing `FeatureStore` + CR in the same k8s cluster. properties: name: + description: Name of the FeatureStore type: string namespace: + description: Namespace of the FeatureStore type: string required: - name type: object hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` type: string tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. properties: certName: + description: defines the configmap key name for + the client TLS cert. type: string configMapRef: + description: references the local k8s configmap + where the TLS cert resides properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2909,63 +4798,108 @@ spec: rule: '[has(self.local), has(self.remote)].exists_one(c, c)' ui: + description: Creates a UI server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -2978,24 +4912,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of + a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must + be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -3004,8 +4956,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -3014,11 +4971,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -3034,6 +5001,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3042,23 +5012,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -3068,21 +5055,43 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of a Volume + within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. type: string required: - mountPath @@ -3091,109 +5100,210 @@ spec: type: array type: object volumes: + description: Volumes specifies the volumes to mount in the + FeatureStore deployment. items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. properties: awsElasticBlockStore: + description: |- + awsElasticBlockStore represents an AWS Disk resource that is attached to a + kubelet's host machine and then exposed to th properties: fsType: + description: fsType is the filesystem type of the + volume that you want to mount. type: string partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. format: int32 type: integer readOnly: + description: |- + readOnly value true will force the readOnly setting in VolumeMounts. + More info: https://kubernetes. type: boolean volumeID: + description: |- + volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). + More info: https://kubernetes. type: string required: - volumeID type: object azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. properties: cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: + description: diskName is the Name of the data disk + in the blob storage type: string diskURI: + description: diskURI is the URI of data disk in + the blob storage type: string fsType: + description: |- + fsType is Filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage accoun' type: string readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. properties: readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime properties: monitors: + description: |- + monitors is Required: Monitors is a collection of Ceph monitors + More info: https://examples.k8s. items: type: string type: array x-kubernetes-list-type: atomic path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' type: string readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.' type: string secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty.' properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic user: + description: |- + user is optional: User is the rados user name, default is admin + More info: https://examples.k8s. type: string required: - monitors type: object cinder: + description: |- + cinder represents a cinder volume attached and mounted on kubelets host machine. + More info: https://examples.k8s. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef is optional: points to a secret object containing parameters used to connect + to OpenStack. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic volumeID: + description: |- + volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md type: string required: - volumeID type: object configMap: + description: configMap represents a configMap that should + populate this volume properties: defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default.' format: int32 type: integer items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum items: + description: Maps a string key to a path within + a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode bits + used to set permissions on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -3203,67 +5313,125 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object x-kubernetes-map-type: atomic csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta fea properties: driver: + description: driver is the name of the CSI driver + that handles this volume. type: string fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". type: string nodePublishSecretRef: + description: |- + nodePublishSecretRef is a reference to the secret object containing + sensitive information to pass to the CSI driver to c properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic readOnly: + description: |- + readOnly specifies a read-only configuration for the volume. + Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string + description: |- + volumeAttributes stores driver-specific properties that are passed to the CSI + driver. type: object required: - driver type: object downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume properties: defaultMode: + description: 'Optional: mode bits to use on created + files by default.' format: int32 type: integer items: + description: Items is a list of downward API volume + file items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field properties: fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name, + namespace and uid are supported.' properties: apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu format: int32 type: integer path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path.' type: string resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. properties: containerName: + description: 'Container name: required + for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource @@ -3276,36 +5444,63 @@ spec: x-kubernetes-list-type: atomic type: object emptyDir: + description: |- + emptyDir represents a temporary directory that shares a pod's lifetime. + More info: https://kubernetes. properties: medium: + description: medium represents what type of storage + medium should back this directory. type: string sizeLimit: anyOf: - type: integer - type: string + description: sizeLimit is the total amount of local + storage required for this EmptyDir volume. 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 ephemeral: + description: ephemeral represents a volume that is handled + by a cluster storage driver. properties: volumeClaimTemplate: + description: Will be used to create a stand-alone + PVC to provision the volume. properties: metadata: + description: |- + May contain labels and annotations that will be copied into the PVC + when creating it. type: object spec: + description: The specification for the PersistentVolumeClaim. properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s. properties: apiGroup: + description: APIGroup is the group for + the resource being referenced. type: string kind: + description: Kind is the type of resource + being referenced type: string name: + description: Name is the name of resource + being referenced type: string required: - kind @@ -3313,20 +5508,34 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. properties: apiGroup: + description: APIGroup is the group for + the resource being referenced. type: string kind: + description: Kind is the type of resource + being referenced type: string name: + description: Name is the name of resource + being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking. type: string required: - kind - name type: object resources: + description: resources represents the minimum + resources the volume should have. properties: limits: additionalProperties: @@ -3335,6 +5544,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3343,18 +5555,38 @@ spec: - 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 + description: Requests describes the + minimum amount of compute resources + required. type: object type: object selector: + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: + description: key is the label + key that the selector applies + to. type: string operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3368,16 +5600,28 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of + {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes. type: string volumeAttributesClassName: + description: volumeAttributesClassName may + be used to set the VolumeAttributesClass + used by this claim. type: string volumeMode: + description: volumeMode defines what type + of volume is required by the claim. type: string volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. type: string type: object required: @@ -3385,41 +5629,78 @@ spec: type: object type: object fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string lun: + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' items: type: string type: array x-kubernetes-list-type: atomic wwids: + description: "wwids Optional: FC volume world wide + identifiers (wwids)\nEither wwids or combination + of targetWWNs and lun must be set, " items: type: string type: array x-kubernetes-list-type: atomic type: object flexVolume: + description: |- + flexVolume represents a generic volume resource that is + provisioned/attached using an exec based plugin. properties: driver: + description: driver is the name of the driver to + use for this volume. type: string fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string options: additionalProperties: type: string + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: + description: |- + readOnly is Optional: defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef is Optional: secretRef is reference to the secret object containing + sensitive information to pass to the plugi properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -3427,90 +5708,171 @@ spec: - driver type: object flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. properties: datasetName: + description: |- + datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker + should be considered as depreca type: string datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: + description: |- + gcePersistentDisk represents a GCE Disk resource that is attached to a + kubelet's host machine and then exposed to the po properties: fsType: + description: fsType is filesystem type of the volume + that you want to mount. type: string partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. format: int32 type: integer pdName: + description: |- + pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. + More info: https://kubernetes. type: string readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://kubernetes. type: boolean required: - pdName type: object gitRepo: + description: |- + gitRepo represents a git repository at a particular revision. + DEPRECATED: GitRepo is deprecated. properties: directory: + description: |- + directory is the target directory name. + Must not contain or start with '..'. If '. type: string repository: + description: repository is the URL type: string revision: + description: revision is the commit hash for the + specified revision. type: string required: - repository type: object glusterfs: + description: |- + glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. properties: endpoints: + description: |- + endpoints is the endpoint name that details Glusterfs topology. + More info: https://examples.k8s. type: string path: + description: |- + path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod type: string readOnly: + description: |- + readOnly here will force the Glusterfs volume to be mounted with read-only permissions. + Defaults to false. type: boolean required: - endpoints - path type: object hostPath: + description: |- + hostPath represents a pre-existing file or directory on the host + machine that is directly exposed to the container. properties: path: + description: |- + path of the directory on the host. + If the path is a symlink, it will follow the link to the real path. type: string type: + description: |- + type for HostPath Volume + Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath type: string required: - path type: object iscsi: + description: |- + iscsi represents an ISCSI Disk resource that is attached to a + kubelet's host machine and then exposed to the pod. properties: chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: + description: fsType is the filesystem type of the + volume that you want to mount. type: string initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. type: string iqn: + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + description: |- + iscsiInterface is the interface Name that uses an iSCSI transport. + Defaults to 'default' (tcp). type: string lun: + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: + description: portals is the iSCSI Target Portal + List. items: type: string type: array x-kubernetes-list-type: atomic readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. type: boolean secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic targetPortal: + description: targetPortal is iSCSI Target Portal. type: string required: - iqn @@ -3518,68 +5880,139 @@ spec: - targetPortal type: object name: + description: |- + name of the volume. + Must be a DNS_LABEL and unique within the pod. + More info: https://kubernetes. type: string nfs: + description: |- + nfs represents an NFS mount on the host that shares a pod's lifetime + More info: https://kubernetes. properties: path: + description: |- + path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs type: string readOnly: + description: |- + readOnly here will force the NFS export to be mounted with read-only permissions. + Defaults to false. type: boolean server: + description: |- + server is the hostname or IP address of the NFS server. + More info: https://kubernetes. type: string required: - path - server type: object persistentVolumeClaim: + description: |- + persistentVolumeClaimVolumeSource represents a reference to a + PersistentVolumeClaim in the same namespace. properties: claimName: + description: claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. type: string readOnly: + description: |- + readOnly Will force the ReadOnly setting in VolumeMounts. + Default false. type: boolean required: - claimName type: object photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk type: string required: - pdID type: object portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine properties: fsType: + description: |- + fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating system. + Ex. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean volumeID: + description: volumeID uniquely identifies a Portworx + volume type: string required: - volumeID type: object projected: + description: projected items for all in one resources + secrets, configmaps, and downward API properties: defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. format: int32 type: integer sources: + description: sources is the list of volume projections items: + description: Projection that may be projected + along with other supported volume types properties: clusterTrustBundle: + description: ClusterTrustBundle allows a pod + to access the `.spec. properties: labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. properties: matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: + description: key is the label + key that the selector applies + to. type: string operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3593,31 +6026,58 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map + of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. type: string optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. type: boolean path: + description: Relative path from the volume + root to write the bundle. type: string signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. type: string required: - path type: object configMap: + description: configMap information about the + configMap data to project properties: items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum items: + description: Maps a string key to a + path within a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -3627,42 +6087,83 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional specify whether + the ConfigMap or its keys must be defined type: boolean type: object x-kubernetes-map-type: atomic downwardAPI: + description: downwardAPI information about + the downwardAPI data to project properties: items: + description: Items is a list of DownwardAPIVolume + file items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field properties: fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name, namespace and uid + are supported.' properties: apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field + to select in the specified + API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu format: int32 type: integer path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path.' type: string resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. properties: containerName: + description: 'Container name: + required for volumes, optional + for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource + to select' type: string required: - resource @@ -3675,16 +6176,30 @@ spec: x-kubernetes-list-type: atomic type: object secret: + description: secret information about the + secret data to project properties: items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a items: + description: Maps a string key to a + path within a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -3694,19 +6209,35 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object x-kubernetes-map-type: atomic serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: + description: audience is the intended + audience of the token. type: string expirationSeconds: + description: |- + expirationSeconds is the requested duration of validity of the service + account token. format: int64 type: integer path: + description: |- + path is the path relative to the mount point of the file to project the + token into. type: string required: - path @@ -3716,79 +6247,164 @@ spec: x-kubernetes-list-type: atomic type: object quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime properties: group: + description: |- + group to map volume access to + Default is no group type: string readOnly: + description: |- + readOnly here will force the Quobyte volume to be mounted with read-only permissions. + Defaults to false. type: boolean registry: + description: |- + registry represents a single or multiple Quobyte Registry services + specified as a string as host:port pair (multiple ent type: string tenant: + description: |- + tenant owning the given Quobyte volume in the Backend + Used with dynamically provisioned Quobyte volumes, value is set by type: string user: + description: |- + user to map volume access to + Defaults to serivceaccount user type: string volume: + description: volume is a string that references + an already created Quobyte volume by name. type: string required: - registry - volume type: object rbd: + description: |- + rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. properties: fsType: + description: fsType is the filesystem type of the + volume that you want to mount. type: string image: + description: |- + image is the rados image name. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + description: |- + keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. + More info: https://examples.k8s. type: string monitors: + description: |- + monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it items: type: string type: array x-kubernetes-list-type: atomic pool: + description: |- + pool is the rados pool name. + Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://examples.k8s. type: boolean secretRef: + description: |- + secretRef is name of the authentication secret for RBDUser. If provided + overrides keyring. + Default is nil. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic user: + description: |- + user is the rados user name. + Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string required: - image - monitors type: object scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string gateway: + description: gateway is the host address of the + ScaleIO API Gateway. type: string protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. type: string readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef references to the secret for ScaleIO user and other + sensitive information. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false type: boolean storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. type: string storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. type: string system: + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: + description: |- + volumeName is the name of a volume already created in the ScaleIO system + that is associated with this volume source. type: string required: - gateway @@ -3796,19 +6412,35 @@ spec: - system type: object secret: + description: |- + secret represents a secret that should populate this volume. + More info: https://kubernetes. properties: defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default.' format: int32 type: integer items: + description: |- + items If unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a items: + description: Maps a string key to a path within + a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode bits + used to set permissions on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -3817,37 +6449,76 @@ spec: type: array x-kubernetes-list-type: atomic optional: + description: optional field specify whether the + Secret or its keys must be defined type: boolean secretName: + description: |- + secretName is the name of the secret in the pod's namespace to use. + More info: https://kubernetes. type: string type: object storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef specifies the secret to use for obtaining the StorageOS API + credentials. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic volumeName: + description: |- + volumeName is the human-readable name of the StorageOS volume. Volume + names are only unique within a namespace. type: string volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. type: string type: object vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine properties: fsType: + description: |- + fsType is filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. type: string storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath @@ -3861,32 +6532,51 @@ spec: - feastProject type: object clientConfigMap: + description: ConfigMap in this namespace containing a client `feature_store.yaml` + for this feast deployment type: string conditions: items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. maxLength: 32768 type: string observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if . format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -3903,6 +6593,8 @@ spec: phase: type: string serviceHostnames: + description: ServiceHostnames defines the service hostnames in the + format of :, e.g. example.svc.cluster.local:80 properties: offlineStore: type: string diff --git a/infra/feast-operator/dist/install.yaml b/infra/feast-operator/dist/install.yaml index 7010ae1caea..3858cc3d4c6 100644 --- a/infra/feast-operator/dist/install.yaml +++ b/infra/feast-operator/dist/install.yaml @@ -34,30 +34,53 @@ spec: name: v1alpha1 schema: openAPIV3Schema: + description: FeatureStore is the Schema for the featurestores API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: FeatureStoreSpec defines the desired state of FeatureStore properties: authz: + description: AuthzConfig defines the authorization settings for the + deployed Feast services. properties: kubernetes: + description: |- + KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. + https://kubernetes. properties: roles: + description: The Kubernetes RBAC roles to be deployed in the + same namespace of the FeatureStore. items: type: string type: array type: object oidc: + description: |- + OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. + https://auth0. properties: secretRef: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -69,45 +92,74 @@ spec: - message: One selection required between kubernetes or oidc. rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' feastProject: + description: FeastProject is the Feast project id. pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ type: string services: + description: FeatureStoreServices defines the desired feast services. + An ephemeral registry is deployed by default. properties: deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. properties: rollingUpdate: + description: |- + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. properties: maxSurge: anyOf: - type: integer - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string + description: The maximum number of pods that can be unavailable + during the update. x-kubernetes-int-or-string: true type: object type: + description: Type of deployment. Can be "Recreate" or "RollingUpdate". + Default is RollingUpdate. type: string type: object disableInitContainers: + description: Disable the 'feast repo initialization' initContainer type: boolean offlineStore: + description: OfflineStore configures the deployed offline store + service properties: persistence: + description: OfflineStorePersistence configures the persistence + settings for the offline store service properties: file: + description: OfflineStoreFilePersistence configures the + file-based persistence for the offline store service properties: pvc: + description: PvcConfig defines the settings for a + persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent volume + access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -116,6 +168,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -124,20 +179,33 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which this + persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -160,17 +228,30 @@ spec: type: string type: object store: + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the secret + key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you want + to use. enum: - snowflake.offline - bigquery @@ -190,63 +271,108 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a remote offline server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -259,24 +385,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of + a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must + be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -285,8 +429,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -295,11 +444,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -315,6 +474,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -323,23 +485,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -349,21 +528,43 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of a Volume + within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. type: string required: - mountPath @@ -373,22 +574,35 @@ spec: type: object type: object onlineStore: + description: OnlineStore configures the deployed online store + service properties: persistence: + description: OnlineStorePersistence configures the persistence + settings for the online store service properties: file: + description: OnlineStoreFilePersistence configures the + file-based persistence for the online store service properties: path: type: string pvc: + description: PvcConfig defines the settings for a + persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent volume + access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -397,6 +611,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -405,20 +622,33 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which this + persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -446,17 +676,30 @@ spec: rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) : true' store: + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the secret + key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you want + to use. enum: - snowflake.online - redis @@ -484,63 +727,108 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a feature server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -553,24 +841,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of + a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must + be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -579,8 +885,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -589,11 +900,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -609,6 +930,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -617,23 +941,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -643,21 +984,43 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of a Volume + within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. type: string required: - mountPath @@ -667,24 +1030,39 @@ spec: type: object type: object registry: + description: Registry configures the registry service. One selection + is required. Local is the default setting. properties: local: + description: LocalRegistryConfig configures the deployed registry + service properties: persistence: + description: RegistryPersistence configures the persistence + settings for the registry service properties: file: + description: RegistryFilePersistence configures the + file-based persistence for the registry service properties: path: type: string pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -693,6 +1071,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -701,20 +1082,34 @@ spec: - 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 + description: Requests describes the + minimum amount of compute resources + required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -754,17 +1149,30 @@ spec: rule: '(has(self.s3_additional_kwargs) && has(self.path)) ? self.path.startsWith(''s3://'') : true' store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you + want to use. enum: - sql - snowflake.registry @@ -779,63 +1187,111 @@ spec: rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a registry server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' properties: apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required + for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to + select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in + the pod's namespace properties: key: + description: The key of the secret to + select from. Must be a valid secret + key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -848,24 +1304,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source + of a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + must be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -874,8 +1348,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -884,11 +1363,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -904,6 +1393,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -912,23 +1404,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for + a feast service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -938,21 +1447,44 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of + a Volume within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. type: string required: - mountPath @@ -962,26 +1494,44 @@ spec: type: object type: object remote: + description: RemoteRegistryConfig points to a remote feast + registry server. properties: feastRef: + description: Reference to an existing `FeatureStore` CR + in the same k8s cluster. properties: name: + description: Name of the FeatureStore type: string namespace: + description: Namespace of the FeatureStore type: string required: - name type: object hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` type: string tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. properties: certName: + description: defines the configmap key name for the + client TLS cert. type: string configMapRef: + description: references the local k8s configmap where + the TLS cert resides properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -999,63 +1549,107 @@ spec: - message: One selection required. rule: '[has(self.local), has(self.remote)].exists_one(c, c)' ui: + description: Creates a UI server container properties: env: items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -1068,24 +1662,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of a set + of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to each + key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must be + defined type: boolean type: object x-kubernetes-map-type: atomic @@ -1094,8 +1706,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when to + pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -1104,11 +1721,20 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute resource + requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -1124,6 +1750,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1132,23 +1761,40 @@ spec: - 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 + description: Requests describes the minimum amount of + compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. useful + in an openshift cluster, for example, where TLS is configured + by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key names + for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where the + TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -1158,21 +1804,43 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes that + should be mounted into the feast container. items: + description: VolumeMount describes a mounting of a Volume + within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. type: string required: - mountPath @@ -1181,109 +1849,209 @@ spec: type: array type: object volumes: + description: Volumes specifies the volumes to mount in the FeatureStore + deployment. items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. properties: awsElasticBlockStore: + description: |- + awsElasticBlockStore represents an AWS Disk resource that is attached to a + kubelet's host machine and then exposed to th properties: fsType: + description: fsType is the filesystem type of the volume + that you want to mount. type: string partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. format: int32 type: integer readOnly: + description: |- + readOnly value true will force the readOnly setting in VolumeMounts. + More info: https://kubernetes. type: boolean volumeID: + description: |- + volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). + More info: https://kubernetes. type: string required: - volumeID type: object azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. properties: cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: + description: diskName is the Name of the data disk in + the blob storage type: string diskURI: + description: diskURI is the URI of data disk in the + blob storage type: string fsType: + description: |- + fsType is Filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage accoun' type: string readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. properties: readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime properties: monitors: + description: |- + monitors is Required: Monitors is a collection of Ceph monitors + More info: https://examples.k8s. items: type: string type: array x-kubernetes-list-type: atomic path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default is /' type: string readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretFile: + description: 'secretFile is Optional: SecretFile is + the path to key ring for User, default is /etc/ceph/user.' type: string secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is + empty.' properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic user: + description: |- + user is optional: User is the rados user name, default is admin + More info: https://examples.k8s. type: string required: - monitors type: object cinder: + description: |- + cinder represents a cinder volume attached and mounted on kubelets host machine. + More info: https://examples.k8s. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef is optional: points to a secret object containing parameters used to connect + to OpenStack. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic volumeID: + description: |- + volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md type: string required: - volumeID type: object configMap: + description: configMap represents a configMap that should + populate this volume properties: defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default.' format: int32 type: integer items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum items: + description: Maps a string key to a path within a + volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode bits used + to set permissions on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -1293,67 +2061,121 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object x-kubernetes-map-type: atomic csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta fea properties: driver: + description: driver is the name of the CSI driver that + handles this volume. type: string fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". type: string nodePublishSecretRef: + description: |- + nodePublishSecretRef is a reference to the secret object containing + sensitive information to pass to the CSI driver to c properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic readOnly: + description: |- + readOnly specifies a read-only configuration for the volume. + Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string + description: |- + volumeAttributes stores driver-specific properties that are passed to the CSI + driver. type: object required: - driver type: object downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume properties: defaultMode: + description: 'Optional: mode bits to use on created + files by default.' format: int32 type: integer items: + description: Items is a list of downward API volume + file items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field properties: fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name, namespace + and uid are supported.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu format: int32 type: integer path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path.' type: string resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource @@ -1366,36 +2188,63 @@ spec: x-kubernetes-list-type: atomic type: object emptyDir: + description: |- + emptyDir represents a temporary directory that shares a pod's lifetime. + More info: https://kubernetes. properties: medium: + description: medium represents what type of storage + medium should back this directory. type: string sizeLimit: anyOf: - type: integer - type: string + description: sizeLimit is the total amount of local + storage required for this EmptyDir volume. 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 ephemeral: + description: ephemeral represents a volume that is handled + by a cluster storage driver. properties: volumeClaimTemplate: + description: Will be used to create a stand-alone PVC + to provision the volume. properties: metadata: + description: |- + May contain labels and annotations that will be copied into the PVC + when creating it. type: object spec: + description: The specification for the PersistentVolumeClaim. properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s. properties: apiGroup: + description: APIGroup is the group for the + resource being referenced. type: string kind: + description: Kind is the type of resource + being referenced type: string name: + description: Name is the name of resource + being referenced type: string required: - kind @@ -1403,20 +2252,34 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. properties: apiGroup: + description: APIGroup is the group for the + resource being referenced. type: string kind: + description: Kind is the type of resource + being referenced type: string name: + description: Name is the name of resource + being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking. type: string required: - kind - name type: object resources: + description: resources represents the minimum + resources the volume should have. properties: limits: additionalProperties: @@ -1425,6 +2288,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1433,18 +2299,36 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object selector: + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: + description: key is the label key + that the selector applies to. type: string operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -1458,16 +2342,28 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes. type: string volumeAttributesClassName: + description: volumeAttributesClassName may be + used to set the VolumeAttributesClass used + by this claim. type: string volumeMode: + description: volumeMode defines what type of + volume is required by the claim. type: string volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. type: string type: object required: @@ -1475,41 +2371,78 @@ spec: type: object type: object fc: + description: fc represents a Fibre Channel resource that + is attached to a kubelet's host machine and then exposed + to the pod. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string lun: + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' items: type: string type: array x-kubernetes-list-type: atomic wwids: + description: "wwids Optional: FC volume world wide identifiers + (wwids)\nEither wwids or combination of targetWWNs + and lun must be set, " items: type: string type: array x-kubernetes-list-type: atomic type: object flexVolume: + description: |- + flexVolume represents a generic volume resource that is + provisioned/attached using an exec based plugin. properties: driver: + description: driver is the name of the driver to use + for this volume. type: string fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string options: additionalProperties: type: string + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: + description: |- + readOnly is Optional: defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef is Optional: secretRef is reference to the secret object containing + sensitive information to pass to the plugi properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -1517,90 +2450,170 @@ spec: - driver type: object flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. properties: datasetName: + description: |- + datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker + should be considered as depreca type: string datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: + description: |- + gcePersistentDisk represents a GCE Disk resource that is attached to a + kubelet's host machine and then exposed to the po properties: fsType: + description: fsType is filesystem type of the volume + that you want to mount. type: string partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. format: int32 type: integer pdName: + description: |- + pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. + More info: https://kubernetes. type: string readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://kubernetes. type: boolean required: - pdName type: object gitRepo: + description: |- + gitRepo represents a git repository at a particular revision. + DEPRECATED: GitRepo is deprecated. properties: directory: + description: |- + directory is the target directory name. + Must not contain or start with '..'. If '. type: string repository: + description: repository is the URL type: string revision: + description: revision is the commit hash for the specified + revision. type: string required: - repository type: object glusterfs: + description: |- + glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. properties: endpoints: + description: |- + endpoints is the endpoint name that details Glusterfs topology. + More info: https://examples.k8s. type: string path: + description: |- + path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod type: string readOnly: + description: |- + readOnly here will force the Glusterfs volume to be mounted with read-only permissions. + Defaults to false. type: boolean required: - endpoints - path type: object hostPath: + description: |- + hostPath represents a pre-existing file or directory on the host + machine that is directly exposed to the container. properties: path: + description: |- + path of the directory on the host. + If the path is a symlink, it will follow the link to the real path. type: string type: + description: |- + type for HostPath Volume + Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath type: string required: - path type: object iscsi: + description: |- + iscsi represents an ISCSI Disk resource that is attached to a + kubelet's host machine and then exposed to the pod. properties: chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: + description: fsType is the filesystem type of the volume + that you want to mount. type: string initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. type: string iqn: + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + description: |- + iscsiInterface is the interface Name that uses an iSCSI transport. + Defaults to 'default' (tcp). type: string lun: + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: + description: portals is the iSCSI Target Portal List. items: type: string type: array x-kubernetes-list-type: atomic readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. type: boolean secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic targetPortal: + description: targetPortal is iSCSI Target Portal. type: string required: - iqn @@ -1608,68 +2621,138 @@ spec: - targetPortal type: object name: + description: |- + name of the volume. + Must be a DNS_LABEL and unique within the pod. + More info: https://kubernetes. type: string nfs: + description: |- + nfs represents an NFS mount on the host that shares a pod's lifetime + More info: https://kubernetes. properties: path: + description: |- + path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs type: string readOnly: + description: |- + readOnly here will force the NFS export to be mounted with read-only permissions. + Defaults to false. type: boolean server: + description: |- + server is the hostname or IP address of the NFS server. + More info: https://kubernetes. type: string required: - path - server type: object persistentVolumeClaim: + description: |- + persistentVolumeClaimVolumeSource represents a reference to a + PersistentVolumeClaim in the same namespace. properties: claimName: + description: claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. type: string readOnly: + description: |- + readOnly Will force the ReadOnly setting in VolumeMounts. + Default false. type: boolean required: - claimName type: object photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk type: string required: - pdID type: object portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine properties: fsType: + description: |- + fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating system. + Ex. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean volumeID: + description: volumeID uniquely identifies a Portworx + volume type: string required: - volumeID type: object projected: + description: projected items for all in one resources secrets, + configmaps, and downward API properties: defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. format: int32 type: integer sources: + description: sources is the list of volume projections items: + description: Projection that may be projected along + with other supported volume types properties: clusterTrustBundle: + description: ClusterTrustBundle allows a pod to + access the `.spec. properties: labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. properties: matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: + description: key is the label key + that the selector applies to. type: string operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -1683,31 +2766,58 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of {key,value} + pairs. type: object type: object x-kubernetes-map-type: atomic name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. type: string optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. type: boolean path: + description: Relative path from the volume + root to write the bundle. type: string signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. type: string required: - path type: object configMap: + description: configMap information about the configMap + data to project properties: items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum items: + description: Maps a string key to a path + within a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -1717,42 +2827,81 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional specify whether the + ConfigMap or its keys must be defined type: boolean type: object x-kubernetes-map-type: atomic downwardAPI: + description: downwardAPI information about the + downwardAPI data to project properties: items: + description: Items is a list of DownwardAPIVolume + file items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field properties: fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name, namespace and uid are supported.' properties: apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". type: string fieldPath: + description: Path of the field to + select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu format: int32 type: integer path: + description: 'Required: Path is the + relative path name of the file to + be created. Must not be absolute or + contain the ''..'' path.' type: string resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. properties: containerName: + description: 'Container name: required + for volumes, optional for env + vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource + to select' type: string required: - resource @@ -1765,16 +2914,30 @@ spec: x-kubernetes-list-type: atomic type: object secret: + description: secret information about the secret + data to project properties: items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a items: + description: Maps a string key to a path + within a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -1784,19 +2947,35 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object x-kubernetes-map-type: atomic serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: + description: audience is the intended audience + of the token. type: string expirationSeconds: + description: |- + expirationSeconds is the requested duration of validity of the service + account token. format: int64 type: integer path: + description: |- + path is the path relative to the mount point of the file to project the + token into. type: string required: - path @@ -1806,79 +2985,164 @@ spec: x-kubernetes-list-type: atomic type: object quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime properties: group: + description: |- + group to map volume access to + Default is no group type: string readOnly: + description: |- + readOnly here will force the Quobyte volume to be mounted with read-only permissions. + Defaults to false. type: boolean registry: + description: |- + registry represents a single or multiple Quobyte Registry services + specified as a string as host:port pair (multiple ent type: string tenant: + description: |- + tenant owning the given Quobyte volume in the Backend + Used with dynamically provisioned Quobyte volumes, value is set by type: string user: + description: |- + user to map volume access to + Defaults to serivceaccount user type: string volume: + description: volume is a string that references an already + created Quobyte volume by name. type: string required: - registry - volume type: object rbd: + description: |- + rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. properties: fsType: + description: fsType is the filesystem type of the volume + that you want to mount. type: string image: + description: |- + image is the rados image name. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + description: |- + keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. + More info: https://examples.k8s. type: string monitors: + description: |- + monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it items: type: string type: array x-kubernetes-list-type: atomic pool: + description: |- + pool is the rados pool name. + Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://examples.k8s. type: boolean secretRef: + description: |- + secretRef is name of the authentication secret for RBDUser. If provided + overrides keyring. + Default is nil. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic user: + description: |- + user is the rados user name. + Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string required: - image - monitors type: object scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string gateway: + description: gateway is the host address of the ScaleIO + API Gateway. type: string protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. type: string readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef references to the secret for ScaleIO user and other + sensitive information. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false type: boolean storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. type: string storagePool: + description: storagePool is the ScaleIO Storage Pool + associated with the protection domain. type: string system: + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: + description: |- + volumeName is the name of a volume already created in the ScaleIO system + that is associated with this volume source. type: string required: - gateway @@ -1886,19 +3150,35 @@ spec: - system type: object secret: + description: |- + secret represents a secret that should populate this volume. + More info: https://kubernetes. properties: defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default.' format: int32 type: integer items: + description: |- + items If unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a items: + description: Maps a string key to a path within a + volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode bits used + to set permissions on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -1907,37 +3187,75 @@ spec: type: array x-kubernetes-list-type: atomic optional: + description: optional field specify whether the Secret + or its keys must be defined type: boolean secretName: + description: |- + secretName is the name of the secret in the pod's namespace to use. + More info: https://kubernetes. type: string type: object storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef specifies the secret to use for obtaining the StorageOS API + credentials. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic volumeName: + description: |- + volumeName is the human-readable name of the StorageOS volume. Volume + names are only unique within a namespace. type: string volumeNamespace: + description: volumeNamespace specifies the scope of + the volume within StorageOS. type: string type: object vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine properties: fsType: + description: |- + fsType is filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. type: string storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath @@ -1951,24 +3269,44 @@ spec: - feastProject type: object status: + description: FeatureStoreStatus defines the observed state of FeatureStore properties: applied: + description: Shows the currently applied feast configuration, including + any pertinent defaults properties: authz: + description: AuthzConfig defines the authorization settings for + the deployed Feast services. properties: kubernetes: + description: |- + KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. + https://kubernetes. properties: roles: + description: The Kubernetes RBAC roles to be deployed + in the same namespace of the FeatureStore. items: type: string type: array type: object oidc: + description: |- + OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. + https://auth0. properties: secretRef: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -1981,45 +3319,75 @@ spec: rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' feastProject: + description: FeastProject is the Feast project id. pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ type: string services: + description: FeatureStoreServices defines the desired feast services. + An ephemeral registry is deployed by default. properties: deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. properties: rollingUpdate: + description: |- + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. properties: maxSurge: anyOf: - type: integer - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string + description: The maximum number of pods that can be + unavailable during the update. x-kubernetes-int-or-string: true type: object type: + description: Type of deployment. Can be "Recreate" or + "RollingUpdate". Default is RollingUpdate. type: string type: object disableInitContainers: + description: Disable the 'feast repo initialization' initContainer type: boolean offlineStore: + description: OfflineStore configures the deployed offline + store service properties: persistence: + description: OfflineStorePersistence configures the persistence + settings for the offline store service properties: file: + description: OfflineStoreFilePersistence configures + the file-based persistence for the offline store + service properties: pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -2028,6 +3396,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2036,20 +3407,34 @@ spec: - 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 + description: Requests describes the + minimum amount of compute resources + required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2072,17 +3457,30 @@ spec: type: string type: object store: + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you + want to use. enum: - snowflake.offline - bigquery @@ -2103,63 +3501,111 @@ spec: rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a remote offline server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' properties: apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required + for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to + select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in + the pod's namespace properties: key: + description: The key of the secret to + select from. Must be a valid secret + key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -2172,24 +3618,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source + of a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + must be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -2198,8 +3662,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -2208,11 +3677,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -2228,6 +3707,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2236,23 +3718,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for + a feast service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2262,21 +3761,44 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of + a Volume within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. type: string required: - mountPath @@ -2286,22 +3808,36 @@ spec: type: object type: object onlineStore: + description: OnlineStore configures the deployed online store + service properties: persistence: + description: OnlineStorePersistence configures the persistence + settings for the online store service properties: file: + description: OnlineStoreFilePersistence configures + the file-based persistence for the online store + service properties: path: type: string pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -2310,6 +3846,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2318,20 +3857,34 @@ spec: - 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 + description: Requests describes the + minimum amount of compute resources + required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2360,17 +3913,30 @@ spec: rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) : true' store: + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you + want to use. enum: - snowflake.online - redis @@ -2399,63 +3965,111 @@ spec: rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a feature server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' properties: apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required + for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to + select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in + the pod's namespace properties: key: + description: The key of the secret to + select from. Must be a valid secret + key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -2468,24 +4082,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source + of a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + must be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -2494,8 +4126,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -2504,11 +4141,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -2524,6 +4171,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2532,23 +4182,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for + a feast service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2558,21 +4225,44 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of + a Volume within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. type: string required: - mountPath @@ -2582,24 +4272,43 @@ spec: type: object type: object registry: + description: Registry configures the registry service. One + selection is required. Local is the default setting. properties: local: + description: LocalRegistryConfig configures the deployed + registry service properties: persistence: + description: RegistryPersistence configures the persistence + settings for the registry service properties: file: + description: RegistryFilePersistence configures + the file-based persistence for the registry + service properties: path: type: string pvc: + description: PvcConfig defines the settings + for a persistent file store based on PVCs. properties: create: + description: Settings for creating a new + PVC properties: accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to + ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the + storage resource requirements for + a volume. properties: limits: additionalProperties: @@ -2608,6 +4317,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2616,20 +4328,36 @@ spec: - 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 + description: Requests describes + the minimum amount of compute + resources required. type: object type: object storageClassName: + description: StorageClassName is the + name of an existing StorageClass + to which this persistent volume + belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing + field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2669,17 +4397,30 @@ spec: rule: '(has(self.s3_additional_kwargs) && has(self.path)) ? self.path.startsWith(''s3://'') : true' store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service properties: secretKeyName: + description: By default, the selected store + "type" is used as the SecretKeyName type: string secretRef: + description: Data store parameters should + be placed as-is from the "feature_store.yaml" + under the secret key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type + you want to use. enum: - sql - snowflake.registry @@ -2695,63 +4436,113 @@ spec: rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: + description: Creates a registry server container properties: env: items: + description: EnvVar represents an environment + variable present in a Container. properties: name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the + ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the + pod: supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' properties: apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". type: string fieldPath: + description: Path of the field to + select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required + for volumes, optional for env + vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource + to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret + in the pod's namespace properties: key: + description: The key of the secret + to select from. Must be a valid + secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the + Secret or its key must be defined type: boolean required: - key @@ -2764,24 +4555,43 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source + of a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be + a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + must be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -2790,8 +4600,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for + if/when to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -2800,11 +4615,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the + compute resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -2820,6 +4645,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -2828,23 +4656,41 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS + for a feast service. properties: disable: + description: will disable TLS for the feast + service. useful in an openshift cluster, + for example, where TLS is configured by + default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret + where the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2855,21 +4701,46 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of + volumes that should be mounted into the feast + container. items: + description: VolumeMount describes a mounting + of a Volume within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of + a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume + from which the container's volume should + be mounted. type: string required: - mountPath @@ -2879,26 +4750,44 @@ spec: type: object type: object remote: + description: RemoteRegistryConfig points to a remote feast + registry server. properties: feastRef: + description: Reference to an existing `FeatureStore` + CR in the same k8s cluster. properties: name: + description: Name of the FeatureStore type: string namespace: + description: Namespace of the FeatureStore type: string required: - name type: object hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` type: string tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. properties: certName: + description: defines the configmap key name for + the client TLS cert. type: string configMapRef: + description: references the local k8s configmap + where the TLS cert resides properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -2917,63 +4806,108 @@ spec: rule: '[has(self.local), has(self.remote)].exists_one(c, c)' ui: + description: Creates a UI server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -2986,24 +4920,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of + a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must + be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -3012,8 +4964,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -3022,11 +4979,21 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -3042,6 +5009,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3050,23 +5020,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -3076,21 +5063,43 @@ spec: rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. items: + description: VolumeMount describes a mounting of a Volume + within a container. properties: mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string name: + description: This must match the Name of a Volume. type: string readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. type: string required: - mountPath @@ -3099,109 +5108,210 @@ spec: type: array type: object volumes: + description: Volumes specifies the volumes to mount in the + FeatureStore deployment. items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. properties: awsElasticBlockStore: + description: |- + awsElasticBlockStore represents an AWS Disk resource that is attached to a + kubelet's host machine and then exposed to th properties: fsType: + description: fsType is the filesystem type of the + volume that you want to mount. type: string partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. format: int32 type: integer readOnly: + description: |- + readOnly value true will force the readOnly setting in VolumeMounts. + More info: https://kubernetes. type: boolean volumeID: + description: |- + volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). + More info: https://kubernetes. type: string required: - volumeID type: object azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. properties: cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: + description: diskName is the Name of the data disk + in the blob storage type: string diskURI: + description: diskURI is the URI of data disk in + the blob storage type: string fsType: + description: |- + fsType is Filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage accoun' type: string readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. properties: readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime properties: monitors: + description: |- + monitors is Required: Monitors is a collection of Ceph monitors + More info: https://examples.k8s. items: type: string type: array x-kubernetes-list-type: atomic path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' type: string readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.' type: string secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty.' properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic user: + description: |- + user is optional: User is the rados user name, default is admin + More info: https://examples.k8s. type: string required: - monitors type: object cinder: + description: |- + cinder represents a cinder volume attached and mounted on kubelets host machine. + More info: https://examples.k8s. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef is optional: points to a secret object containing parameters used to connect + to OpenStack. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic volumeID: + description: |- + volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md type: string required: - volumeID type: object configMap: + description: configMap represents a configMap that should + populate this volume properties: defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default.' format: int32 type: integer items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum items: + description: Maps a string key to a path within + a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode bits + used to set permissions on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -3211,67 +5321,125 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object x-kubernetes-map-type: atomic csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta fea properties: driver: + description: driver is the name of the CSI driver + that handles this volume. type: string fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". type: string nodePublishSecretRef: + description: |- + nodePublishSecretRef is a reference to the secret object containing + sensitive information to pass to the CSI driver to c properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic readOnly: + description: |- + readOnly specifies a read-only configuration for the volume. + Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string + description: |- + volumeAttributes stores driver-specific properties that are passed to the CSI + driver. type: object required: - driver type: object downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume properties: defaultMode: + description: 'Optional: mode bits to use on created + files by default.' format: int32 type: integer items: + description: Items is a list of downward API volume + file items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field properties: fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name, + namespace and uid are supported.' properties: apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu format: int32 type: integer path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path.' type: string resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. properties: containerName: + description: 'Container name: required + for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource @@ -3284,36 +5452,63 @@ spec: x-kubernetes-list-type: atomic type: object emptyDir: + description: |- + emptyDir represents a temporary directory that shares a pod's lifetime. + More info: https://kubernetes. properties: medium: + description: medium represents what type of storage + medium should back this directory. type: string sizeLimit: anyOf: - type: integer - type: string + description: sizeLimit is the total amount of local + storage required for this EmptyDir volume. 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 ephemeral: + description: ephemeral represents a volume that is handled + by a cluster storage driver. properties: volumeClaimTemplate: + description: Will be used to create a stand-alone + PVC to provision the volume. properties: metadata: + description: |- + May contain labels and annotations that will be copied into the PVC + when creating it. type: object spec: + description: The specification for the PersistentVolumeClaim. properties: accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: type: string type: array x-kubernetes-list-type: atomic dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s. properties: apiGroup: + description: APIGroup is the group for + the resource being referenced. type: string kind: + description: Kind is the type of resource + being referenced type: string name: + description: Name is the name of resource + being referenced type: string required: - kind @@ -3321,20 +5516,34 @@ spec: type: object x-kubernetes-map-type: atomic dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. properties: apiGroup: + description: APIGroup is the group for + the resource being referenced. type: string kind: + description: Kind is the type of resource + being referenced type: string name: + description: Name is the name of resource + being referenced type: string namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking. type: string required: - kind - name type: object resources: + description: resources represents the minimum + resources the volume should have. properties: limits: additionalProperties: @@ -3343,6 +5552,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -3351,18 +5563,38 @@ spec: - 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 + description: Requests describes the + minimum amount of compute resources + required. type: object type: object selector: + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: + description: key is the label + key that the selector applies + to. type: string operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3376,16 +5608,28 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map of + {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes. type: string volumeAttributesClassName: + description: volumeAttributesClassName may + be used to set the VolumeAttributesClass + used by this claim. type: string volumeMode: + description: volumeMode defines what type + of volume is required by the claim. type: string volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. type: string type: object required: @@ -3393,41 +5637,78 @@ spec: type: object type: object fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string lun: + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' items: type: string type: array x-kubernetes-list-type: atomic wwids: + description: "wwids Optional: FC volume world wide + identifiers (wwids)\nEither wwids or combination + of targetWWNs and lun must be set, " items: type: string type: array x-kubernetes-list-type: atomic type: object flexVolume: + description: |- + flexVolume represents a generic volume resource that is + provisioned/attached using an exec based plugin. properties: driver: + description: driver is the name of the driver to + use for this volume. type: string fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string options: additionalProperties: type: string + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: + description: |- + readOnly is Optional: defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef is Optional: secretRef is reference to the secret object containing + sensitive information to pass to the plugi properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -3435,90 +5716,171 @@ spec: - driver type: object flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. properties: datasetName: + description: |- + datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker + should be considered as depreca type: string datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: + description: |- + gcePersistentDisk represents a GCE Disk resource that is attached to a + kubelet's host machine and then exposed to the po properties: fsType: + description: fsType is filesystem type of the volume + that you want to mount. type: string partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. format: int32 type: integer pdName: + description: |- + pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. + More info: https://kubernetes. type: string readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://kubernetes. type: boolean required: - pdName type: object gitRepo: + description: |- + gitRepo represents a git repository at a particular revision. + DEPRECATED: GitRepo is deprecated. properties: directory: + description: |- + directory is the target directory name. + Must not contain or start with '..'. If '. type: string repository: + description: repository is the URL type: string revision: + description: revision is the commit hash for the + specified revision. type: string required: - repository type: object glusterfs: + description: |- + glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. properties: endpoints: + description: |- + endpoints is the endpoint name that details Glusterfs topology. + More info: https://examples.k8s. type: string path: + description: |- + path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod type: string readOnly: + description: |- + readOnly here will force the Glusterfs volume to be mounted with read-only permissions. + Defaults to false. type: boolean required: - endpoints - path type: object hostPath: + description: |- + hostPath represents a pre-existing file or directory on the host + machine that is directly exposed to the container. properties: path: + description: |- + path of the directory on the host. + If the path is a symlink, it will follow the link to the real path. type: string type: + description: |- + type for HostPath Volume + Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath type: string required: - path type: object iscsi: + description: |- + iscsi represents an ISCSI Disk resource that is attached to a + kubelet's host machine and then exposed to the pod. properties: chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: + description: fsType is the filesystem type of the + volume that you want to mount. type: string initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. type: string iqn: + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + description: |- + iscsiInterface is the interface Name that uses an iSCSI transport. + Defaults to 'default' (tcp). type: string lun: + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: + description: portals is the iSCSI Target Portal + List. items: type: string type: array x-kubernetes-list-type: atomic readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. type: boolean secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic targetPortal: + description: targetPortal is iSCSI Target Portal. type: string required: - iqn @@ -3526,68 +5888,139 @@ spec: - targetPortal type: object name: + description: |- + name of the volume. + Must be a DNS_LABEL and unique within the pod. + More info: https://kubernetes. type: string nfs: + description: |- + nfs represents an NFS mount on the host that shares a pod's lifetime + More info: https://kubernetes. properties: path: + description: |- + path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs type: string readOnly: + description: |- + readOnly here will force the NFS export to be mounted with read-only permissions. + Defaults to false. type: boolean server: + description: |- + server is the hostname or IP address of the NFS server. + More info: https://kubernetes. type: string required: - path - server type: object persistentVolumeClaim: + description: |- + persistentVolumeClaimVolumeSource represents a reference to a + PersistentVolumeClaim in the same namespace. properties: claimName: + description: claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. type: string readOnly: + description: |- + readOnly Will force the ReadOnly setting in VolumeMounts. + Default false. type: boolean required: - claimName type: object photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk type: string required: - pdID type: object portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine properties: fsType: + description: |- + fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating system. + Ex. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean volumeID: + description: volumeID uniquely identifies a Portworx + volume type: string required: - volumeID type: object projected: + description: projected items for all in one resources + secrets, configmaps, and downward API properties: defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. format: int32 type: integer sources: + description: sources is the list of volume projections items: + description: Projection that may be projected + along with other supported volume types properties: clusterTrustBundle: + description: ClusterTrustBundle allows a pod + to access the `.spec. properties: labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. properties: matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: + description: key is the label + key that the selector applies + to. type: string operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. items: type: string type: array @@ -3601,31 +6034,58 @@ spec: matchLabels: additionalProperties: type: string + description: matchLabels is a map + of {key,value} pairs. type: object type: object x-kubernetes-map-type: atomic name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. type: string optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. type: boolean path: + description: Relative path from the volume + root to write the bundle. type: string signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. type: string required: - path type: object configMap: + description: configMap information about the + configMap data to project properties: items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum items: + description: Maps a string key to a + path within a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -3635,42 +6095,83 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional specify whether + the ConfigMap or its keys must be defined type: boolean type: object x-kubernetes-map-type: atomic downwardAPI: + description: downwardAPI information about + the downwardAPI data to project properties: items: + description: Items is a list of DownwardAPIVolume + file items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field properties: fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name, namespace and uid + are supported.' properties: apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field + to select in the specified + API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu format: int32 type: integer path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path.' type: string resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. properties: containerName: + description: 'Container name: + required for volumes, optional + for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource + to select' type: string required: - resource @@ -3683,16 +6184,30 @@ spec: x-kubernetes-list-type: atomic type: object secret: + description: secret information about the + secret data to project properties: items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a items: + description: Maps a string key to a + path within a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -3702,19 +6217,35 @@ spec: x-kubernetes-list-type: atomic name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object x-kubernetes-map-type: atomic serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: + description: audience is the intended + audience of the token. type: string expirationSeconds: + description: |- + expirationSeconds is the requested duration of validity of the service + account token. format: int64 type: integer path: + description: |- + path is the path relative to the mount point of the file to project the + token into. type: string required: - path @@ -3724,79 +6255,164 @@ spec: x-kubernetes-list-type: atomic type: object quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime properties: group: + description: |- + group to map volume access to + Default is no group type: string readOnly: + description: |- + readOnly here will force the Quobyte volume to be mounted with read-only permissions. + Defaults to false. type: boolean registry: + description: |- + registry represents a single or multiple Quobyte Registry services + specified as a string as host:port pair (multiple ent type: string tenant: + description: |- + tenant owning the given Quobyte volume in the Backend + Used with dynamically provisioned Quobyte volumes, value is set by type: string user: + description: |- + user to map volume access to + Defaults to serivceaccount user type: string volume: + description: volume is a string that references + an already created Quobyte volume by name. type: string required: - registry - volume type: object rbd: + description: |- + rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. properties: fsType: + description: fsType is the filesystem type of the + volume that you want to mount. type: string image: + description: |- + image is the rados image name. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + description: |- + keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. + More info: https://examples.k8s. type: string monitors: + description: |- + monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it items: type: string type: array x-kubernetes-list-type: atomic pool: + description: |- + pool is the rados pool name. + Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://examples.k8s. type: boolean secretRef: + description: |- + secretRef is name of the authentication secret for RBDUser. If provided + overrides keyring. + Default is nil. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic user: + description: |- + user is the rados user name. + Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string required: - image - monitors type: object scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string gateway: + description: gateway is the host address of the + ScaleIO API Gateway. type: string protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. type: string readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef references to the secret for ScaleIO user and other + sensitive information. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false type: boolean storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. type: string storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. type: string system: + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: + description: |- + volumeName is the name of a volume already created in the ScaleIO system + that is associated with this volume source. type: string required: - gateway @@ -3804,19 +6420,35 @@ spec: - system type: object secret: + description: |- + secret represents a secret that should populate this volume. + More info: https://kubernetes. properties: defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default.' format: int32 type: integer items: + description: |- + items If unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a items: + description: Maps a string key to a path within + a volume. properties: key: + description: key is the key to project. type: string mode: + description: 'mode is Optional: mode bits + used to set permissions on this file.' format: int32 type: integer path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. type: string required: - key @@ -3825,37 +6457,76 @@ spec: type: array x-kubernetes-list-type: atomic optional: + description: optional field specify whether the + Secret or its keys must be defined type: boolean secretName: + description: |- + secretName is the name of the secret in the pod's namespace to use. + More info: https://kubernetes. type: string type: object storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. properties: fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean secretRef: + description: |- + secretRef specifies the secret to use for obtaining the StorageOS API + credentials. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic volumeName: + description: |- + volumeName is the human-readable name of the StorageOS volume. Volume + names are only unique within a namespace. type: string volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. type: string type: object vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine properties: fsType: + description: |- + fsType is filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. type: string storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath @@ -3869,32 +6540,51 @@ spec: - feastProject type: object clientConfigMap: + description: ConfigMap in this namespace containing a client `feature_store.yaml` + for this feast deployment type: string conditions: items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. maxLength: 32768 type: string observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if . format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -3911,6 +6601,8 @@ spec: phase: type: string serviceHostnames: + description: ServiceHostnames defines the service hostnames in the + format of :, e.g. example.svc.cluster.local:80 properties: offlineStore: type: string From b87683e4917f6165687f3bd9b2980e890a5e8ba0 Mon Sep 17 00:00:00 2001 From: Pertsev Alexei Date: Thu, 13 Feb 2025 15:44:36 +0300 Subject: [PATCH 23/30] doc: Fix links (#5052) Signed-off-by: Alexei Pertsev --- docs/README.md | 2 +- docs/getting-started/components/offline-store.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 73c6860137e..02ecaefa10c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -56,7 +56,7 @@ Feast helps ML platform/MLOps teams with DevOps experience productionize real-ti ### Feast is not -* **An** [**ETL**](https://en.wikipedia.org/wiki/Extract,\_transform,\_load) / [**ELT**](https://en.wikipedia.org/wiki/Extract,\_load,\_transform) **system.** Feast is not a general purpose data pipelining system. Users often leverage tools like [dbt](https://www.getdbt.com) to manage upstream data transformations. Feast does support some [transformations](getting-started/architecture/feature-transformetion.md). +* **An** [**ETL**](https://en.wikipedia.org/wiki/Extract,\_transform,\_load) / [**ELT**](https://en.wikipedia.org/wiki/Extract,\_load,\_transform) **system.** Feast is not a general purpose data pipelining system. Users often leverage tools like [dbt](https://www.getdbt.com) to manage upstream data transformations. Feast does support some [transformations](getting-started/architecture/feature-transformation.md). * **A data orchestration tool:** Feast does not manage or orchestrate complex workflow DAGs. It relies on upstream data pipelines to produce feature values and integrations with tools like [Airflow](https://airflow.apache.org) to make features consistently available. * **A data warehouse:** Feast is not a replacement for your data warehouse or the source of truth for all transformed data in your organization. Rather, Feast is a lightweight downstream layer that can serve data from an existing data warehouse (or other data sources) to models in production. * **A database:** Feast is not a database, but helps manage data stored in other systems (e.g. BigQuery, Snowflake, DynamoDB, Redis) to make features consistently available at training / serving time diff --git a/docs/getting-started/components/offline-store.md b/docs/getting-started/components/offline-store.md index 48470c6547a..c04773e66b4 100644 --- a/docs/getting-started/components/offline-store.md +++ b/docs/getting-started/components/offline-store.md @@ -8,7 +8,7 @@ Offline stores are primarily used for two reasons: 1. Building training datasets from time-series features. 2. Materializing \(loading\) features into an online store to serve those features at low-latency in a production setting. -Offline stores are configured through the [feature\_store.yaml](../../reference/offline-stores/). +Offline stores are configured through the [feature\_store.yaml](../../reference/feature-repository/feature-store-yaml.md). When building training datasets or materializing features into an online store, Feast will use the configured offline store with your configured data sources to execute the necessary data operations. Only a single offline store can be used at a time. From 6c92447d1507bff02451f77f134df0a24cbd8036 Mon Sep 17 00:00:00 2001 From: Tommy Hughes IV Date: Thu, 13 Feb 2025 12:28:37 -0600 Subject: [PATCH 24/30] fix: Operator - make onlineStore the default service (#5044) make onlineStore the default service Signed-off-by: Tommy Hughes --- examples/operator-quickstart/01-Install.ipynb | 101 +++--- examples/operator-quickstart/02-Demo.ipynb | 315 ++++++++++++------ .../operator-quickstart/03-Uninstall.ipynb | 10 +- examples/operator-quickstart/feast.yaml | 22 +- infra/feast-operator/Makefile | 2 +- .../api/v1alpha1/featurestore_types.go | 8 +- .../crd/bases/feast.dev_featurestores.yaml | 23 +- .../v1alpha1_featurestore_all_servers.yaml | 5 +- .../v1alpha1_featurestore_db_persistence.yaml | 10 +- ...a1_featurestore_ephemeral_persistence.yaml | 20 -- ...v1alpha1_featurestore_kubernetes_auth.yaml | 14 - ..._featurestore_objectstore_persistence.yaml | 8 - .../v1alpha1_featurestore_oidc_auth.yaml | 14 - ...a1_featurestore_openshift_tls_disable.yaml | 24 -- ..._featurestore_postgres_db_volumes_ssl.yaml | 18 +- infra/feast-operator/dist/install.yaml | 23 +- infra/feast-operator/docs/api/markdown/ref.md | 51 ++- .../featurestore_controller_db_store_test.go | 16 +- .../featurestore_controller_ephemeral_test.go | 10 +- .../featurestore_controller_loglevel_test.go | 6 +- ...eaturestore_controller_objectstore_test.go | 29 +- .../featurestore_controller_pvc_test.go | 16 +- .../featurestore_controller_test.go | 42 +-- ...featurestore_controller_test_utils_test.go | 5 + .../controller/services/repo_config_test.go | 11 +- .../internal/controller/services/services.go | 32 +- .../internal/controller/services/tls.go | 13 +- .../internal/controller/services/tls_test.go | 14 +- .../internal/controller/services/util.go | 87 ++--- .../v1alpha1_default_featurestore.yaml | 5 +- ...v1alpha1_remote_registry_featurestore.yaml | 2 - 31 files changed, 499 insertions(+), 457 deletions(-) delete mode 100644 infra/feast-operator/config/samples/v1alpha1_featurestore_ephemeral_persistence.yaml delete mode 100644 infra/feast-operator/config/samples/v1alpha1_featurestore_openshift_tls_disable.yaml diff --git a/examples/operator-quickstart/01-Install.ipynb b/examples/operator-quickstart/01-Install.ipynb index d703357f791..e2396efb4a0 100644 --- a/examples/operator-quickstart/01-Install.ipynb +++ b/examples/operator-quickstart/01-Install.ipynb @@ -74,7 +74,7 @@ "output_type": "stream", "text": [ "NAME STATUS AGE\n", - "feast Active 3s\n" + "feast Active 10s\n" ] } ], @@ -133,7 +133,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -141,20 +141,20 @@ "output_type": "stream", "text": [ "NAME READY STATUS RESTARTS AGE\n", - "pod/postgres-ff8d4cf48-bqvfm 1/1 Running 0 99s\n", - "pod/redis-b4756b75d-fxkst 1/1 Running 0 98s\n", + "pod/postgres-ff8d4cf48-6nqhs 1/1 Running 0 70s\n", + "pod/redis-b4756b75d-nttdm 1/1 Running 0 68s\n", "\n", "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\n", - "service/postgres ClusterIP 10.43.197.94 5432/TCP 99s\n", - "service/redis ClusterIP 10.43.137.235 6379/TCP 98s\n", + "service/postgres ClusterIP 10.43.203.123 5432/TCP 70s\n", + "service/redis ClusterIP 10.43.234.211 6379/TCP 67s\n", "\n", "NAME READY UP-TO-DATE AVAILABLE AGE\n", - "deployment.apps/postgres 1/1 1 1 99s\n", - "deployment.apps/redis 1/1 1 1 98s\n", + "deployment.apps/postgres 1/1 1 1 70s\n", + "deployment.apps/redis 1/1 1 1 69s\n", "\n", "NAME DESIRED CURRENT READY AGE\n", - "replicaset.apps/postgres-ff8d4cf48 1 1 1 99s\n", - "replicaset.apps/redis-b4756b75d 1 1 1 98s\n" + "replicaset.apps/postgres-ff8d4cf48 1 1 1 70s\n", + "replicaset.apps/redis-b4756b75d 1 1 1 68s\n" ] } ], @@ -171,7 +171,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -217,7 +217,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 1, "metadata": {}, "outputs": [ { @@ -243,34 +243,32 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "NAME READY STATUS RESTARTS AGE\n", - "pod/feast-example-74d5c98984-sr9bs 0/3 Init:0/1 0 4m43s\n", - "pod/postgres-ff8d4cf48-bqvfm 1/1 Running 0 7m36s\n", - "pod/redis-b4756b75d-fxkst 1/1 Running 0 7m35s\n", + "NAME READY STATUS RESTARTS AGE\n", + "pod/feast-example-556689b95c-gb227 0/1 PodInitializing 0 6m41s\n", + "pod/postgres-ff8d4cf48-6nqhs 1/1 Running 0 10m\n", + "pod/redis-b4756b75d-nttdm 1/1 Running 0 10m\n", "\n", - "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\n", - "service/feast-example-offline ClusterIP 10.43.81.130 80/TCP 4m44s\n", - "service/feast-example-online ClusterIP 10.43.74.219 80/TCP 4m43s\n", - "service/feast-example-registry ClusterIP 10.43.52.126 80/TCP 4m43s\n", - "service/postgres ClusterIP 10.43.197.94 5432/TCP 7m36s\n", - "service/redis ClusterIP 10.43.137.235 6379/TCP 7m35s\n", + "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\n", + "service/feast-example-online ClusterIP 10.43.254.136 80/TCP 6m43s\n", + "service/postgres ClusterIP 10.43.203.123 5432/TCP 10m\n", + "service/redis ClusterIP 10.43.234.211 6379/TCP 10m\n", "\n", "NAME READY UP-TO-DATE AVAILABLE AGE\n", - "deployment.apps/feast-example 0/1 1 0 4m43s\n", - "deployment.apps/postgres 1/1 1 1 7m36s\n", - "deployment.apps/redis 1/1 1 1 7m35s\n", + "deployment.apps/feast-example 0/1 1 0 6m43s\n", + "deployment.apps/postgres 1/1 1 1 10m\n", + "deployment.apps/redis 1/1 1 1 10m\n", "\n", "NAME DESIRED CURRENT READY AGE\n", - "replicaset.apps/feast-example-74d5c98984 1 1 0 4m43s\n", - "replicaset.apps/postgres-ff8d4cf48 1 1 1 7m36s\n", - "replicaset.apps/redis-b4756b75d 1 1 1 7m35s\n", + "replicaset.apps/feast-example-556689b95c 1 1 0 6m43s\n", + "replicaset.apps/postgres-ff8d4cf48 1 1 1 10m\n", + "replicaset.apps/redis-b4756b75d 1 1 1 10m\n", "deployment.apps/feast-example condition met\n" ] } @@ -289,7 +287,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -297,7 +295,7 @@ "output_type": "stream", "text": [ "NAME STATUS AGE\n", - "example Ready 10m\n" + "example Ready 7m39s\n" ] } ], @@ -314,7 +312,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -354,7 +352,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -383,7 +381,7 @@ "/feast-data/credit_scoring_local/feature_repo/example_repo.py:27: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'driver'.\n", " driver = Entity(name=\"driver\", join_keys=[\"driver_id\"])\n", "Applying changes for project credit_scoring_local\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/feature_store.py:578: RuntimeWarning: On demand feature view is an experimental feature. This API is stable, but the functionality does not scale well for offline retrieval\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/feature_store.py:579: RuntimeWarning: On demand feature view is an experimental feature. This API is stable, but the functionality does not scale well for offline retrieval\n", " warnings.warn(\n", "Deploying infrastructure for \u001b[1m\u001b[32mdriver_hourly_stats\u001b[0m\n", "Deploying infrastructure for \u001b[1m\u001b[32mdriver_hourly_stats_fresh\u001b[0m\n" @@ -391,8 +389,8 @@ } ], "source": [ - "!kubectl exec deploy/feast-example -itc registry -- cat feature_store.yaml\n", - "!kubectl exec deploy/feast-example -itc registry -- feast apply" + "!kubectl exec deploy/feast-example -itc online -- cat feature_store.yaml\n", + "!kubectl exec deploy/feast-example -itc online -- feast apply" ] }, { @@ -404,7 +402,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -413,29 +411,29 @@ "text": [ "/opt/app-root/lib64/python3.11/site-packages/feast/feature_view.py:48: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " DUMMY_ENTITY = Entity(\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'driver'.\n", - " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'driver'.\n", + " entity = cls(\n", "NAME DESCRIPTION TAGS OWNER\n", "credit_scoring_local A project for driver statistics {}\n", "/opt/app-root/lib64/python3.11/site-packages/feast/feature_view.py:48: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " DUMMY_ENTITY = Entity(\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'driver'.\n", - " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'driver'.\n", + " entity = cls(\n", "NAME ENTITIES TYPE\n", "driver_hourly_stats {'driver'} FeatureView\n", "driver_hourly_stats_fresh {'driver'} FeatureView\n", - "transformed_conv_rate {'driver'} OnDemandFeatureView\n", - "transformed_conv_rate_fresh {'driver'} OnDemandFeatureView\n" + "transformed_conv_rate_fresh {'driver'} OnDemandFeatureView\n", + "transformed_conv_rate {'driver'} OnDemandFeatureView\n" ] } ], "source": [ - "!kubectl exec deploy/feast-example -itc registry -- feast projects list\n", - "!kubectl exec deploy/feast-example -itc registry -- feast feature-views list" + "!kubectl exec deploy/feast-example -itc online -- feast projects list\n", + "!kubectl exec deploy/feast-example -itc online -- feast feature-views list" ] }, { @@ -447,7 +445,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -456,13 +454,20 @@ "text": [ "/opt/app-root/lib64/python3.11/site-packages/feast/feature_view.py:48: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " DUMMY_ENTITY = Entity(\n", - "Feast SDK Version: \"0.43.0\"\n" + "Feast SDK Version: \"0.45.0\"\n" ] } ], "source": [ - "!kubectl exec deployment/feast-example -itc registry -- feast version" + "!kubectl exec deployment/feast-example -itc online -- feast version" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/examples/operator-quickstart/02-Demo.ipynb b/examples/operator-quickstart/02-Demo.ipynb index 51e26ba3616..5ad4395d2fa 100644 --- a/examples/operator-quickstart/02-Demo.ipynb +++ b/examples/operator-quickstart/02-Demo.ipynb @@ -32,29 +32,13 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "--2025-01-23 18:09:13-- https://github.com/feast-dev/feast-credit-score-local-tutorial/archive/f43b44b.tar.gz\n", - "Resolving github.com (github.com)... 140.82.112.4\n", - "Connecting to github.com (github.com)|140.82.112.4|:443... connected.\n", - "HTTP request sent, awaiting response... 302 Found\n", - "Location: https://codeload.github.com/feast-dev/feast-credit-score-local-tutorial/tar.gz/f43b44b245ae2632b582f14176392cfe31f98da9 [following]\n", - "--2025-01-23 18:09:13-- https://codeload.github.com/feast-dev/feast-credit-score-local-tutorial/tar.gz/f43b44b245ae2632b582f14176392cfe31f98da9\n", - "Resolving codeload.github.com (codeload.github.com)... 140.82.114.10\n", - "Connecting to codeload.github.com (codeload.github.com)|140.82.114.10|:443... connected.\n", - "HTTP request sent, awaiting response... 200 OK\n", - "Length: unspecified [application/x-gzip]\n", - "Saving to: ‘f43b44b.tar.gz’\n", - "\n", - "f43b44b.tar.gz [ <=> ] 45.52M 10.8MB/s in 5.0s \n", - "\n", - "2025-01-23 18:09:19 (9.12 MB/s) - ‘f43b44b.tar.gz’ saved [47734189]\n", - "\n", "feast-credit-score-local-tutorial-f43b44b245ae2632b582f14176392cfe31f98da9/.gitignore\n", "feast-credit-score-local-tutorial-f43b44b245ae2632b582f14176392cfe31f98da9/LICENSE\n", "feast-credit-score-local-tutorial-f43b44b245ae2632b582f14176392cfe31f98da9/README.md\n", @@ -88,10 +72,10 @@ ], "source": [ "![ -f f43b44b.tar.gz ] || wget https://github.com/feast-dev/feast-credit-score-local-tutorial/archive/f43b44b.tar.gz\n", - "!kubectl cp f43b44b.tar.gz $(kubectl get pods -l 'feast.dev/name=example' -ojsonpath=\"{.items[*].metadata.name}\"):/feast-data -c registry\n", - "!kubectl exec deploy/feast-example -itc registry -- rm -rf /feast-data/feast-credit-score-local-tutorial\n", - "!kubectl exec deploy/feast-example -itc registry -- mkdir /feast-data/feast-credit-score-local-tutorial\n", - "!kubectl exec deploy/feast-example -itc registry -- tar vfx /feast-data/f43b44b.tar.gz -C /feast-data/feast-credit-score-local-tutorial --strip-components 1" + "!kubectl cp f43b44b.tar.gz $(kubectl get pods -l 'feast.dev/name=example' -ojsonpath=\"{.items[*].metadata.name}\"):/feast-data -c online\n", + "!kubectl exec deploy/feast-example -itc online -- rm -rf /feast-data/feast-credit-score-local-tutorial\n", + "!kubectl exec deploy/feast-example -itc online -- mkdir /feast-data/feast-credit-score-local-tutorial\n", + "!kubectl exec deploy/feast-example -itc online -- tar vfx /feast-data/f43b44b.tar.gz -C /feast-data/feast-credit-score-local-tutorial --strip-components 1" ] }, { @@ -110,7 +94,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -138,8 +122,8 @@ } ], "source": [ - "!kubectl exec deploy/feast-example -itc registry -- cp -f /feast-data/credit_scoring_local/feature_repo/feature_store.yaml /feast-data/feast-credit-score-local-tutorial/feature_repo/feature_store.yaml\n", - "!kubectl exec deploy/feast-example -itc registry -- cat /feast-data/feast-credit-score-local-tutorial/feature_repo/feature_store.yaml" + "!kubectl exec deploy/feast-example -itc online -- cp -f /feast-data/credit_scoring_local/feature_repo/feature_store.yaml /feast-data/feast-credit-score-local-tutorial/feature_repo/feature_store.yaml\n", + "!kubectl exec deploy/feast-example -itc online -- cat /feast-data/feast-credit-score-local-tutorial/feature_repo/feature_store.yaml" ] }, { @@ -158,7 +142,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -168,26 +152,26 @@ "/opt/app-root/lib64/python3.11/site-packages/feast/feature_view.py:48: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " DUMMY_ENTITY = Entity(\n", "No project found in the repository. Using project name credit_scoring_local defined in feature_store.yaml\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'driver'.\n", - " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " entity = cls(\n", - "Applying changes for project credit_scoring_local\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'driver'.\n", " entity = cls(\n", + "Applying changes for project credit_scoring_local\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " entity = cls(\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/feature_store.py:578: RuntimeWarning: On demand feature view is an experimental feature. This API is stable, but the functionality does not scale well for offline retrieval\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'driver'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/feature_store.py:579: RuntimeWarning: On demand feature view is an experimental feature. This API is stable, but the functionality does not scale well for offline retrieval\n", " warnings.warn(\n", - "Deploying infrastructure for \u001b[1m\u001b[32mcredit_history\u001b[0m\n", "Deploying infrastructure for \u001b[1m\u001b[32mzipcode_features\u001b[0m\n", - "Removing infrastructure for \u001b[1m\u001b[31mdriver_hourly_stats_fresh\u001b[0m\n", - "Removing infrastructure for \u001b[1m\u001b[31mdriver_hourly_stats\u001b[0m\n" + "Deploying infrastructure for \u001b[1m\u001b[32mcredit_history\u001b[0m\n", + "Removing infrastructure for \u001b[1m\u001b[31mdriver_hourly_stats\u001b[0m\n", + "Removing infrastructure for \u001b[1m\u001b[31mdriver_hourly_stats_fresh\u001b[0m\n" ] } ], "source": [ - "!kubectl exec deploy/feast-example -itc registry -- feast -c /feast-data/feast-credit-score-local-tutorial/feature_repo apply" + "!kubectl exec deploy/feast-example -itc online -- feast -c /feast-data/feast-credit-score-local-tutorial/feature_repo apply" ] }, { @@ -199,7 +183,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -210,25 +194,25 @@ " DUMMY_ENTITY = Entity(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " entity = cls(\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", - " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", " entity = cls(\n", - "Materializing \u001b[1m\u001b[32m2\u001b[0m feature views to \u001b[1m\u001b[32m2025-01-24 00:10:49+00:00\u001b[0m into the \u001b[1m\u001b[32mredis\u001b[0m online store.\n", - "\n", - "\u001b[1m\u001b[32mcredit_history\u001b[0m from \u001b[1m\u001b[32m2024-10-26 00:11:25+00:00\u001b[0m to \u001b[1m\u001b[32m2025-01-24 00:10:49+00:00\u001b[0m:\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", " entity = cls(\n", - "0it [00:00, ?it/s]\n", - "\u001b[1m\u001b[32mzipcode_features\u001b[0m from \u001b[1m\u001b[32m2015-01-27 00:11:41+00:00\u001b[0m to \u001b[1m\u001b[32m2025-01-24 00:10:49+00:00\u001b[0m:\n", + "Materializing \u001b[1m\u001b[32m2\u001b[0m feature views to \u001b[1m\u001b[32m2025-02-11 22:39:40+00:00\u001b[0m into the \u001b[1m\u001b[32mredis\u001b[0m online store.\n", + "\n", + "\u001b[1m\u001b[32mzipcode_features\u001b[0m from \u001b[1m\u001b[32m2015-02-14 22:40:15+00:00\u001b[0m to \u001b[1m\u001b[32m2025-02-11 22:39:40+00:00\u001b[0m:\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", " entity = cls(\n", - "100%|███████████████████████████████████████████████████████| 28844/28844 [00:26<00:00, 1090.11it/s]\n" + "100%|███████████████████████████████████████████████████████| 28844/28844 [00:24<00:00, 1168.09it/s]\n", + "\u001b[1m\u001b[32mcredit_history\u001b[0m from \u001b[1m\u001b[32m2024-11-13 22:40:43+00:00\u001b[0m to \u001b[1m\u001b[32m2025-02-11 22:39:40+00:00\u001b[0m:\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", + " entity = cls(\n", + "0it [00:00, ?it/s]\n" ] } ], "source": [ - "!kubectl exec deploy/feast-example -itc registry -- bash -c 'cd /feast-data/feast-credit-score-local-tutorial/feature_repo && feast materialize-incremental $(date -u +\"%Y-%m-%dT%H:%M:%S\")'" + "!kubectl exec deploy/feast-example -itc online -- bash -c 'cd /feast-data/feast-credit-score-local-tutorial/feature_repo && feast materialize-incremental $(date -u +\"%Y-%m-%dT%H:%M:%S\")'" ] }, { @@ -247,7 +231,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -258,37 +242,37 @@ " DUMMY_ENTITY = Entity(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " entity = cls(\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", - " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", + " entity = cls(\n", "NAME ENTITIES TYPE\n", - "credit_history {'dob_ssn'} FeatureView\n", "zipcode_features {'zipcode'} FeatureView\n", + "credit_history {'dob_ssn'} FeatureView\n", "total_debt_calc {'dob_ssn'} OnDemandFeatureView\n", "/opt/app-root/lib64/python3.11/site-packages/feast/feature_view.py:48: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " DUMMY_ENTITY = Entity(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " entity = cls(\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", - " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", " entity = cls(\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", - " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", + " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", + " entity = cls(\n", "NAME DESCRIPTION TYPE\n", - "zipcode ValueType.INT64\n", - "dob_ssn Date of birth and last four digits of social security number ValueType.STRING\n" + "dob_ssn Date of birth and last four digits of social security number ValueType.STRING\n", + "zipcode ValueType.INT64\n" ] } ], "source": [ - "!kubectl exec deploy/feast-example -itc registry -- feast -c /feast-data/feast-credit-score-local-tutorial/feature_repo feature-views list\n", - "!kubectl exec deploy/feast-example -itc registry -- feast -c /feast-data/feast-credit-score-local-tutorial/feature_repo entities list" + "!kubectl exec deploy/feast-example -itc online -- feast -c /feast-data/feast-credit-score-local-tutorial/feature_repo feature-views list\n", + "!kubectl exec deploy/feast-example -itc online -- feast -c /feast-data/feast-credit-score-local-tutorial/feature_repo entities list" ] }, { @@ -307,7 +291,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -315,134 +299,170 @@ "output_type": "stream", "text": [ "Collecting streamlit (from -r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", - " Downloading streamlit-1.41.1-py2.py3-none-any.whl.metadata (8.5 kB)\n", + " Obtaining dependency information for streamlit from https://files.pythonhosted.org/packages/ad/dc/69068179e09488d0833a970d06e8bf40e35669a7bddb8a3caadc13b7dff4/streamlit-1.42.0-py2.py3-none-any.whl.metadata\n", + " Downloading streamlit-1.42.0-py2.py3-none-any.whl.metadata (8.9 kB)\n", "Collecting shap (from -r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 2))\n", + " Obtaining dependency information for shap from https://files.pythonhosted.org/packages/06/6a/09e3cb9864118337c0f3c2a0dc5add6b642e9f672665062e186d67ba992d/shap-0.46.0-cp311-cp311-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", " Downloading shap-0.46.0-cp311-cp311-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (24 kB)\n", "Requirement already satisfied: pandas in /opt/app-root/lib64/python3.11/site-packages (from -r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 3)) (2.2.3)\n", "Collecting scikit-learn (from -r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 4))\n", + " Obtaining dependency information for scikit-learn from https://files.pythonhosted.org/packages/a8/f3/62fc9a5a659bb58a03cdd7e258956a5824bdc9b4bb3c5d932f55880be569/scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", " Downloading scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (18 kB)\n", "Collecting matplotlib (from -r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 5))\n", + " Obtaining dependency information for matplotlib from https://files.pythonhosted.org/packages/b2/7d/2d873209536b9ee17340754118a2a17988bc18981b5b56e6715ee07373ac/matplotlib-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", " Downloading matplotlib-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (11 kB)\n", "Collecting altair<6,>=4.0 (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + " Obtaining dependency information for altair<6,>=4.0 from https://files.pythonhosted.org/packages/aa/f3/0b6ced594e51cc95d8c1fc1640d3623770d01e4969d29c0bd09945fafefa/altair-5.5.0-py3-none-any.whl.metadata\n", " Downloading altair-5.5.0-py3-none-any.whl.metadata (11 kB)\n", "Collecting blinker<2,>=1.0.0 (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + " Obtaining dependency information for blinker<2,>=1.0.0 from https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl.metadata\n", " Downloading blinker-1.9.0-py3-none-any.whl.metadata (1.6 kB)\n", "Requirement already satisfied: cachetools<6,>=4.0 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (5.5.1)\n", "Requirement already satisfied: click<9,>=7.0 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (8.1.8)\n", "Requirement already satisfied: numpy<3,>=1.23 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (1.26.4)\n", "Requirement already satisfied: packaging<25,>=20 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (24.2)\n", "Collecting pillow<12,>=7.1.0 (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + " Obtaining dependency information for pillow<12,>=7.1.0 from https://files.pythonhosted.org/packages/48/a4/fbfe9d5581d7b111b28f1d8c2762dee92e9821bb209af9fa83c940e507a0/pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl.metadata\n", " Downloading pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl.metadata (9.1 kB)\n", - "Requirement already satisfied: protobuf<6,>=3.20 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (4.25.5)\n", + "Requirement already satisfied: protobuf<6,>=3.20 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (5.29.3)\n", "Requirement already satisfied: pyarrow>=7.0 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (17.0.0)\n", "Requirement already satisfied: requests<3,>=2.27 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (2.32.3)\n", "Requirement already satisfied: rich<14,>=10.14.0 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (13.9.4)\n", "Requirement already satisfied: tenacity<10,>=8.1.0 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (8.5.0)\n", "Requirement already satisfied: toml<2,>=0.10.1 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (0.10.2)\n", - "Requirement already satisfied: typing-extensions<5,>=4.3.0 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (4.12.2)\n", + "Requirement already satisfied: typing-extensions<5,>=4.4.0 in /opt/app-root/lib64/python3.11/site-packages (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (4.12.2)\n", "Collecting watchdog<7,>=2.1.5 (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + " Obtaining dependency information for watchdog<7,>=2.1.5 from https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl.metadata\n", " Downloading watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl.metadata (44 kB)\n", - "Collecting gitpython!=3.1.19,<4,>=3.0.7 (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m44.3/44.3 kB\u001b[0m \u001b[31m5.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting gitpython!=3.1.19,<4,>=3.0.7 (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + " Obtaining dependency information for gitpython!=3.1.19,<4,>=3.0.7 from https://files.pythonhosted.org/packages/1d/9a/4114a9057db2f1462d5c8f8390ab7383925fe1ac012eaa42402ad65c2963/GitPython-3.1.44-py3-none-any.whl.metadata\n", " Downloading GitPython-3.1.44-py3-none-any.whl.metadata (13 kB)\n", "Collecting pydeck<1,>=0.8.0b4 (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + " Obtaining dependency information for pydeck<1,>=0.8.0b4 from https://files.pythonhosted.org/packages/ab/4c/b888e6cf58bd9db9c93f40d1c6be8283ff49d88919231afe93a6bcf61626/pydeck-0.9.1-py2.py3-none-any.whl.metadata\n", " Downloading pydeck-0.9.1-py2.py3-none-any.whl.metadata (4.1 kB)\n", "Collecting tornado<7,>=6.0.3 (from streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + " Obtaining dependency information for tornado<7,>=6.0.3 from https://files.pythonhosted.org/packages/22/55/b78a464de78051a30599ceb6983b01d8f732e6f69bf37b4ed07f642ac0fc/tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", " Downloading tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (2.5 kB)\n", "Collecting scipy (from shap->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 2))\n", + " Obtaining dependency information for scipy from https://files.pythonhosted.org/packages/fc/da/452e1119e6f720df3feb588cce3c42c5e3d628d4bfd4aec097bd30b7de0c/scipy-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", " Downloading scipy-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (61 kB)\n", - "Requirement already satisfied: tqdm>=4.27.0 in /opt/app-root/lib64/python3.11/site-packages (from shap->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 2)) (4.67.1)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m62.0/62.0 kB\u001b[0m \u001b[31m8.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: tqdm>=4.27.0 in /opt/app-root/lib64/python3.11/site-packages (from shap->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 2)) (4.67.1)\n", "Collecting slicer==0.0.8 (from shap->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 2))\n", + " Obtaining dependency information for slicer==0.0.8 from https://files.pythonhosted.org/packages/63/81/9ef641ff4e12cbcca30e54e72fb0951a2ba195d0cda0ba4100e532d929db/slicer-0.0.8-py3-none-any.whl.metadata\n", " Downloading slicer-0.0.8-py3-none-any.whl.metadata (4.0 kB)\n", "Collecting numba (from shap->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 2))\n", + " Obtaining dependency information for numba from https://files.pythonhosted.org/packages/14/91/18b9f64b34ff318a14d072251480547f89ebfb864b2b7168e5dc5f64f502/numba-0.61.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata\n", " Downloading numba-0.61.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (2.8 kB)\n", "Requirement already satisfied: cloudpickle in /opt/app-root/lib64/python3.11/site-packages (from shap->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 2)) (3.1.1)\n", "Requirement already satisfied: python-dateutil>=2.8.2 in /opt/app-root/lib64/python3.11/site-packages (from pandas->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 3)) (2.9.0.post0)\n", - "Requirement already satisfied: pytz>=2020.1 in /opt/app-root/lib64/python3.11/site-packages (from pandas->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 3)) (2024.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /opt/app-root/lib64/python3.11/site-packages (from pandas->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 3)) (2025.1)\n", "Requirement already satisfied: tzdata>=2022.7 in /opt/app-root/lib64/python3.11/site-packages (from pandas->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 3)) (2025.1)\n", "Collecting joblib>=1.2.0 (from scikit-learn->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 4))\n", + " Obtaining dependency information for joblib>=1.2.0 from https://files.pythonhosted.org/packages/91/29/df4b9b42f2be0b623cbd5e2140cafcaa2bef0759a00b7b70104dcfe2fb51/joblib-1.4.2-py3-none-any.whl.metadata\n", " Downloading joblib-1.4.2-py3-none-any.whl.metadata (5.4 kB)\n", "Collecting threadpoolctl>=3.1.0 (from scikit-learn->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 4))\n", + " Obtaining dependency information for threadpoolctl>=3.1.0 from https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl.metadata\n", " Downloading threadpoolctl-3.5.0-py3-none-any.whl.metadata (13 kB)\n", "Collecting contourpy>=1.0.1 (from matplotlib->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 5))\n", + " Obtaining dependency information for contourpy>=1.0.1 from https://files.pythonhosted.org/packages/85/fc/7fa5d17daf77306840a4e84668a48ddff09e6bc09ba4e37e85ffc8e4faa3/contourpy-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", " Downloading contourpy-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (5.4 kB)\n", "Collecting cycler>=0.10 (from matplotlib->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 5))\n", + " Obtaining dependency information for cycler>=0.10 from https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl.metadata\n", " Downloading cycler-0.12.1-py3-none-any.whl.metadata (3.8 kB)\n", "Collecting fonttools>=4.22.0 (from matplotlib->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 5))\n", - " Downloading fonttools-4.55.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (165 kB)\n", - "Collecting kiwisolver>=1.3.1 (from matplotlib->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 5))\n", + " Obtaining dependency information for fonttools>=4.22.0 from https://files.pythonhosted.org/packages/28/e9/47c02d5a7027e8ed841ab6a10ca00c93dadd5f16742f1af1fa3f9978adf4/fonttools-4.56.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", + " Downloading fonttools-4.56.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (101 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m101.9/101.9 kB\u001b[0m \u001b[31m10.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting kiwisolver>=1.3.1 (from matplotlib->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 5))\n", + " Obtaining dependency information for kiwisolver>=1.3.1 from https://files.pythonhosted.org/packages/3a/97/5edbed69a9d0caa2e4aa616ae7df8127e10f6586940aa683a496c2c280b9/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", " Downloading kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (6.2 kB)\n", "Collecting pyparsing>=2.3.1 (from matplotlib->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 5))\n", + " Obtaining dependency information for pyparsing>=2.3.1 from https://files.pythonhosted.org/packages/1c/a7/c8a2d361bf89c0d9577c934ebb7421b25dc84bf3a8e3ac0a40aed9acc547/pyparsing-3.2.1-py3-none-any.whl.metadata\n", " Downloading pyparsing-3.2.1-py3-none-any.whl.metadata (5.0 kB)\n", "Requirement already satisfied: jinja2 in /opt/app-root/lib64/python3.11/site-packages (from altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (3.1.5)\n", "Requirement already satisfied: jsonschema>=3.0 in /opt/app-root/lib64/python3.11/site-packages (from altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (4.23.0)\n", "Collecting narwhals>=1.14.2 (from altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", - " Downloading narwhals-1.23.0-py3-none-any.whl.metadata (10.0 kB)\n", + " Obtaining dependency information for narwhals>=1.14.2 from https://files.pythonhosted.org/packages/15/fc/420680ad8b0cf81372eee7a213a7b7173ec5a628f0d5b2426047fe55c3b3/narwhals-1.26.0-py3-none-any.whl.metadata\n", + " Downloading narwhals-1.26.0-py3-none-any.whl.metadata (10 kB)\n", "Collecting gitdb<5,>=4.0.1 (from gitpython!=3.1.19,<4,>=3.0.7->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + " Obtaining dependency information for gitdb<5,>=4.0.1 from https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl.metadata\n", " Downloading gitdb-4.0.12-py3-none-any.whl.metadata (1.2 kB)\n", "Requirement already satisfied: six>=1.5 in /opt/app-root/lib64/python3.11/site-packages (from python-dateutil>=2.8.2->pandas->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 3)) (1.17.0)\n", "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/app-root/lib64/python3.11/site-packages (from requests<3,>=2.27->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (3.4.1)\n", "Requirement already satisfied: idna<4,>=2.5 in /opt/app-root/lib64/python3.11/site-packages (from requests<3,>=2.27->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (3.10)\n", "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/app-root/lib64/python3.11/site-packages (from requests<3,>=2.27->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (2.3.0)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /opt/app-root/lib64/python3.11/site-packages (from requests<3,>=2.27->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (2024.12.14)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /opt/app-root/lib64/python3.11/site-packages (from requests<3,>=2.27->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (2025.1.31)\n", "Requirement already satisfied: markdown-it-py>=2.2.0 in /opt/app-root/lib64/python3.11/site-packages (from rich<14,>=10.14.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (3.0.0)\n", "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /opt/app-root/lib64/python3.11/site-packages (from rich<14,>=10.14.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (2.19.1)\n", "Collecting llvmlite<0.45,>=0.44.0dev0 (from numba->shap->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 2))\n", + " Obtaining dependency information for llvmlite<0.45,>=0.44.0dev0 from https://files.pythonhosted.org/packages/99/fe/d030f1849ebb1f394bb3f7adad5e729b634fb100515594aca25c354ffc62/llvmlite-0.44.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", " Downloading llvmlite-0.44.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.8 kB)\n", "Collecting smmap<6,>=3.0.1 (from gitdb<5,>=4.0.1->gitpython!=3.1.19,<4,>=3.0.7->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1))\n", + " Obtaining dependency information for smmap<6,>=3.0.1 from https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl.metadata\n", " Downloading smmap-5.0.2-py3-none-any.whl.metadata (4.3 kB)\n", "Requirement already satisfied: MarkupSafe>=2.0 in /opt/app-root/lib64/python3.11/site-packages (from jinja2->altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (3.0.2)\n", - "Requirement already satisfied: attrs>=22.2.0 in /opt/app-root/lib64/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (24.3.0)\n", + "Requirement already satisfied: attrs>=22.2.0 in /opt/app-root/lib64/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (25.1.0)\n", "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /opt/app-root/lib64/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (2024.10.1)\n", - "Requirement already satisfied: referencing>=0.28.4 in /opt/app-root/lib64/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (0.36.1)\n", + "Requirement already satisfied: referencing>=0.28.4 in /opt/app-root/lib64/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (0.36.2)\n", "Requirement already satisfied: rpds-py>=0.7.1 in /opt/app-root/lib64/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (0.22.3)\n", "Requirement already satisfied: mdurl~=0.1 in /opt/app-root/lib64/python3.11/site-packages (from markdown-it-py>=2.2.0->rich<14,>=10.14.0->streamlit->-r /feast-data/feast-credit-score-local-tutorial/requirements.txt (line 1)) (0.1.2)\n", - "Downloading streamlit-1.41.1-py2.py3-none-any.whl (9.1 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m9.1/9.1 MB\u001b[0m \u001b[31m7.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "Downloading streamlit-1.42.0-py2.py3-none-any.whl (9.6 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m9.6/9.6 MB\u001b[0m \u001b[31m5.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", "\u001b[?25hDownloading shap-0.46.0-cp311-cp311-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (540 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m540.2/540.2 kB\u001b[0m \u001b[31m14.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m540.2/540.2 kB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0mta \u001b[36m0:00:01\u001b[0m\n", "\u001b[?25hDownloading slicer-0.0.8-py3-none-any.whl (15 kB)\n", "Downloading scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (13.5 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.5/13.5 MB\u001b[0m \u001b[31m11.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\u001b[36m0:00:01\u001b[0mm\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.5/13.5 MB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", "\u001b[?25hDownloading matplotlib-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (8.6 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m8.6/8.6 MB\u001b[0m \u001b[31m11.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m8.6/8.6 MB\u001b[0m \u001b[31m2.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", "\u001b[?25hDownloading altair-5.5.0-py3-none-any.whl (731 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m731.2/731.2 kB\u001b[0m \u001b[31m12.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m731.2/731.2 kB\u001b[0m \u001b[31m2.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", "\u001b[?25hDownloading blinker-1.9.0-py3-none-any.whl (8.5 kB)\n", "Downloading contourpy-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (326 kB)\n", - "Downloading cycler-0.12.1-py3-none-any.whl (8.3 kB)\n", - "Downloading fonttools-4.55.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.9 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.9/4.9 MB\u001b[0m \u001b[31m15.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m326.2/326.2 kB\u001b[0m \u001b[31m1.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[?25hDownloading cycler-0.12.1-py3-none-any.whl (8.3 kB)\n", + "Downloading fonttools-4.56.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.9 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.9/4.9 MB\u001b[0m \u001b[31m2.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", "\u001b[?25hDownloading GitPython-3.1.44-py3-none-any.whl (207 kB)\n", - "Downloading joblib-1.4.2-py3-none-any.whl (301 kB)\n", - "Downloading kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.4/1.4 MB\u001b[0m \u001b[31m19.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m207.6/207.6 kB\u001b[0m \u001b[31m1.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[?25hDownloading joblib-1.4.2-py3-none-any.whl (301 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m301.8/301.8 kB\u001b[0m \u001b[31m4.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[?25hDownloading kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.4/1.4 MB\u001b[0m \u001b[31m2.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", "\u001b[?25hDownloading pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl (4.5 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.5/4.5 MB\u001b[0m \u001b[31m12.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.5/4.5 MB\u001b[0m \u001b[31m2.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", "\u001b[?25hDownloading pydeck-0.9.1-py2.py3-none-any.whl (6.9 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.9/6.9 MB\u001b[0m \u001b[31m14.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.9/6.9 MB\u001b[0m \u001b[31m3.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", "\u001b[?25hDownloading pyparsing-3.2.1-py3-none-any.whl (107 kB)\n", - "Downloading scipy-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (40.6 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m40.6/40.6 MB\u001b[0m \u001b[31m11.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m107.7/107.7 kB\u001b[0m \u001b[31m7.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading scipy-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (40.6 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m40.6/40.6 MB\u001b[0m \u001b[31m4.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", "\u001b[?25hDownloading threadpoolctl-3.5.0-py3-none-any.whl (18 kB)\n", "Downloading tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (437 kB)\n", - "Downloading watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl (79 kB)\n", - "Downloading numba-0.61.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (3.8 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.8/3.8 MB\u001b[0m \u001b[31m12.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m437.2/437.2 kB\u001b[0m \u001b[31m4.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[?25hDownloading watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl (79 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m79.1/79.1 kB\u001b[0m \u001b[31m7.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading numba-0.61.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (3.8 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.8/3.8 MB\u001b[0m \u001b[31m2.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", "\u001b[?25hDownloading gitdb-4.0.12-py3-none-any.whl (62 kB)\n", - "Downloading llvmlite-0.44.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (42.4 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.4/42.4 MB\u001b[0m \u001b[31m11.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25hDownloading narwhals-1.23.0-py3-none-any.whl (306 kB)\n", - "Downloading smmap-5.0.2-py3-none-any.whl (24 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m62.8/62.8 kB\u001b[0m \u001b[31m9.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading llvmlite-0.44.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (42.4 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.4/42.4 MB\u001b[0m \u001b[31m3.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", + "\u001b[?25hDownloading narwhals-1.26.0-py3-none-any.whl (306 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m306.6/306.6 kB\u001b[0m \u001b[31m12.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading smmap-5.0.2-py3-none-any.whl (24 kB)\n", "Installing collected packages: watchdog, tornado, threadpoolctl, smmap, slicer, scipy, pyparsing, pillow, narwhals, llvmlite, kiwisolver, joblib, fonttools, cycler, contourpy, blinker, scikit-learn, pydeck, numba, matplotlib, gitdb, shap, gitpython, altair, streamlit\n", - "Successfully installed altair-5.5.0 blinker-1.9.0 contourpy-1.3.1 cycler-0.12.1 fonttools-4.55.5 gitdb-4.0.12 gitpython-3.1.44 joblib-1.4.2 kiwisolver-1.4.8 llvmlite-0.44.0 matplotlib-3.10.0 narwhals-1.23.0 numba-0.61.0 pillow-11.1.0 pydeck-0.9.1 pyparsing-3.2.1 scikit-learn-1.6.1 scipy-1.15.1 shap-0.46.0 slicer-0.0.8 smmap-5.0.2 streamlit-1.41.1 threadpoolctl-3.5.0 tornado-6.4.2 watchdog-6.0.0\n", + "Successfully installed altair-5.5.0 blinker-1.9.0 contourpy-1.3.1 cycler-0.12.1 fonttools-4.56.0 gitdb-4.0.12 gitpython-3.1.44 joblib-1.4.2 kiwisolver-1.4.8 llvmlite-0.44.0 matplotlib-3.10.0 narwhals-1.26.0 numba-0.61.0 pillow-11.1.0 pydeck-0.9.1 pyparsing-3.2.1 scikit-learn-1.6.1 scipy-1.15.1 shap-0.46.0 slicer-0.0.8 smmap-5.0.2 streamlit-1.42.0 threadpoolctl-3.5.0 tornado-6.4.2 watchdog-6.0.0\n", "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.2\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.0.1\u001b[0m\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" ] } ], "source": [ - "!kubectl exec deploy/feast-example -itc registry -- bash -c 'pip install -r /feast-data/feast-credit-score-local-tutorial/requirements.txt'" + "!kubectl exec deploy/feast-example -itc online -- bash -c 'pip install -r /feast-data/feast-credit-score-local-tutorial/requirements.txt'" ] }, { @@ -454,7 +474,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -465,22 +485,22 @@ " DUMMY_ENTITY = Entity(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", " entity = cls(\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", - " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", " entity = cls(\n", - "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", - " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", + " entity = cls(\n", "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", + " entity = cls(\n", "Loan rejected!\n" ] } ], "source": [ - "!kubectl exec deploy/feast-example -itc registry -- bash -c 'cd /feast-data/feast-credit-score-local-tutorial && python run.py'" + "!kubectl exec deploy/feast-example -itc online -- bash -c 'cd /feast-data/feast-credit-score-local-tutorial && python run.py'" ] }, { @@ -524,14 +544,101 @@ "\u001b[34m\u001b[1m You can now view your Streamlit app in your browser.\u001b[0m\n", "\u001b[0m\n", "\u001b[34m Local URL: \u001b[0m\u001b[1mhttp://localhost:8501\u001b[0m\n", - "\u001b[34m Network URL: \u001b[0m\u001b[1mhttp://10.42.0.8:8501\u001b[0m\n", + "\u001b[34m Network URL: \u001b[0m\u001b[1mhttp://10.42.0.9:8501\u001b[0m\n", "\u001b[34m External URL: \u001b[0m\u001b[1mhttp://23.112.66.217:8501\u001b[0m\n", - "\u001b[0m\n" + "\u001b[0m\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/feature_view.py:48: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", + " DUMMY_ENTITY = Entity(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", + " entity = cls(\n", + "(1000, 22)\n", + "2025-02-11 22:51:06.834 \n", + "Calling `st.pyplot()` without providing a figure argument has been deprecated\n", + "and will be removed in a later version as it requires the use of Matplotlib's\n", + "global figure object, which is not thread-safe.\n", + "\n", + "To future-proof this code, you should pass in a figure as shown below:\n", + "\n", + "```python\n", + "fig, ax = plt.subplots()\n", + "ax.scatter([1, 2, 3], [1, 2, 3])\n", + "# other plotting actions...\n", + "st.pyplot(fig)\n", + "```\n", + "\n", + "If you have a specific use case that requires this functionality, please let us\n", + "know via [issue on Github](https://github.com/streamlit/streamlit/issues).\n", + "\n", + "2025-02-11 22:51:16.333 \n", + "Calling `st.pyplot()` without providing a figure argument has been deprecated\n", + "and will be removed in a later version as it requires the use of Matplotlib's\n", + "global figure object, which is not thread-safe.\n", + "\n", + "To future-proof this code, you should pass in a figure as shown below:\n", + "\n", + "```python\n", + "fig, ax = plt.subplots()\n", + "ax.scatter([1, 2, 3], [1, 2, 3])\n", + "# other plotting actions...\n", + "st.pyplot(fig)\n", + "```\n", + "\n", + "If you have a specific use case that requires this functionality, please let us\n", + "know via [issue on Github](https://github.com/streamlit/streamlit/issues).\n", + "\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity '__dummy'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'zipcode'.\n", + " entity = cls(\n", + "/opt/app-root/lib64/python3.11/site-packages/feast/entity.py:173: DeprecationWarning: Entity value_type will be mandatory in the next release. Please specify a value_type for entity 'dob_ssn'.\n", + " entity = cls(\n", + "(1000, 22)\n", + "2025-02-11 22:51:57.241 \n", + "Calling `st.pyplot()` without providing a figure argument has been deprecated\n", + "and will be removed in a later version as it requires the use of Matplotlib's\n", + "global figure object, which is not thread-safe.\n", + "\n", + "To future-proof this code, you should pass in a figure as shown below:\n", + "\n", + "```python\n", + "fig, ax = plt.subplots()\n", + "ax.scatter([1, 2, 3], [1, 2, 3])\n", + "# other plotting actions...\n", + "st.pyplot(fig)\n", + "```\n", + "\n", + "If you have a specific use case that requires this functionality, please let us\n", + "know via [issue on Github](https://github.com/streamlit/streamlit/issues).\n", + "\n" ] } ], "source": [ - "!kubectl exec deploy/feast-example -itc registry -- bash -c 'cd /feast-data/feast-credit-score-local-tutorial && streamlit run --server.port 8501 streamlit_app.py'" + "!kubectl exec deploy/feast-example -itc online -- bash -c 'cd /feast-data/feast-credit-score-local-tutorial && streamlit run --server.port 8501 streamlit_app.py'" ] }, { diff --git a/examples/operator-quickstart/03-Uninstall.ipynb b/examples/operator-quickstart/03-Uninstall.ipynb index 02ebedcb50b..3abd489dd58 100644 --- a/examples/operator-quickstart/03-Uninstall.ipynb +++ b/examples/operator-quickstart/03-Uninstall.ipynb @@ -63,14 +63,20 @@ "name": "stdout", "output_type": "stream", "text": [ - "NAME READY STATUS RESTARTS AGE\n", - "pod/feast-example-74d5c98984-sr9bs 2/3 Terminating 2 (18m ago) 27m\n" + "No resources found in feast namespace.\n" ] } ], "source": [ "!kubectl get all" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/examples/operator-quickstart/feast.yaml b/examples/operator-quickstart/feast.yaml index d1d7e4df867..4fa166425cb 100644 --- a/examples/operator-quickstart/feast.yaml +++ b/examples/operator-quickstart/feast.yaml @@ -31,6 +31,17 @@ spec: type: redis secretRef: name: feast-data-stores + server: + envFrom: + - secretRef: + name: postgres-secret + env: + - name: MPLCONFIGDIR + value: /tmp + resources: + requests: + cpu: 150m + memory: 128Mi registry: local: persistence: @@ -38,14 +49,3 @@ spec: type: sql secretRef: name: feast-data-stores - server: - envFrom: - - secretRef: - name: postgres-secret - env: - - name: MPLCONFIGDIR - value: /tmp - resources: - requests: - cpu: 150m - memory: 128Mi diff --git a/infra/feast-operator/Makefile b/infra/feast-operator/Makefile index 223053d0a8f..e272e963837 100644 --- a/infra/feast-operator/Makefile +++ b/infra/feast-operator/Makefile @@ -298,7 +298,7 @@ $(CRD_REF_DOCS): $(LOCALBIN) .PHONY: generate-ref generate-ref: generate fmt crd-ref-docs - $(CRD_REF_DOCS) --log-level=WARN --config=$(LOCALDIR)/docs/crd-ref-templates/config.yaml --source-path=$(LOCALDIR)/api/v1alpha1 --renderer=markdown --templates-dir=$(LOCALDIR)/docs/crd-ref-templates/markdown --output-path=$(LOCALDIR)/docs/api/markdown/ref.md + $(CRD_REF_DOCS) --log-level=WARN --max-depth=30 --config=$(LOCALDIR)/docs/crd-ref-templates/config.yaml --source-path=$(LOCALDIR)/api/v1alpha1 --renderer=markdown --templates-dir=$(LOCALDIR)/docs/crd-ref-templates/markdown --output-path=$(LOCALDIR)/docs/api/markdown/ref.md .PHONY: bundle bundle: manifests kustomize related-image-fs operator-sdk ## Generate bundle manifests and metadata, then validate generated files. diff --git a/infra/feast-operator/api/v1alpha1/featurestore_types.go b/infra/feast-operator/api/v1alpha1/featurestore_types.go index 9c25d2c1d4b..48e70a2804d 100644 --- a/infra/feast-operator/api/v1alpha1/featurestore_types.go +++ b/infra/feast-operator/api/v1alpha1/featurestore_types.go @@ -71,7 +71,7 @@ type FeatureStoreSpec struct { AuthzConfig *AuthzConfig `json:"authz,omitempty"` } -// FeatureStoreServices defines the desired feast services. An ephemeral registry is deployed by default. +// FeatureStoreServices defines the desired feast services. An ephemeral onlineStore feature server is deployed by default. type FeatureStoreServices struct { OfflineStore *OfflineStore `json:"offlineStore,omitempty"` OnlineStore *OnlineStore `json:"onlineStore,omitempty"` @@ -85,7 +85,7 @@ type FeatureStoreServices struct { Volumes []corev1.Volume `json:"volumes,omitempty"` } -// OfflineStore configures the deployed offline store service +// OfflineStore configures the offline store service type OfflineStore struct { // Creates a remote offline server container Server *ServerConfigs `json:"server,omitempty"` @@ -134,7 +134,7 @@ var ValidOfflineStoreDBStorePersistenceTypes = []string{ "mssql", } -// OnlineStore configures the deployed online store service +// OnlineStore configures the online store service type OnlineStore struct { // Creates a feature server container Server *ServerConfigs `json:"server,omitempty"` @@ -187,7 +187,7 @@ var ValidOnlineStoreDBStorePersistenceTypes = []string{ "milvus", } -// LocalRegistryConfig configures the deployed registry service +// LocalRegistryConfig configures the registry service type LocalRegistryConfig struct { // Creates a registry server container Server *ServerConfigs `json:"server,omitempty"` 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 324411eb877..54c48d70575 100644 --- a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml +++ b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml @@ -89,7 +89,7 @@ spec: type: string services: description: FeatureStoreServices defines the desired feast services. - An ephemeral registry is deployed by default. + An ephemeral onlineStore feature server is deployed by default. properties: deploymentStrategy: description: DeploymentStrategy describes how to replace existing @@ -125,8 +125,7 @@ spec: description: Disable the 'feast repo initialization' initContainer type: boolean offlineStore: - description: OfflineStore configures the deployed offline store - service + description: OfflineStore configures the offline store service properties: persistence: description: OfflineStorePersistence configures the persistence @@ -566,8 +565,7 @@ spec: type: object type: object onlineStore: - description: OnlineStore configures the deployed online store - service + description: OnlineStore configures the online store service properties: persistence: description: OnlineStorePersistence configures the persistence @@ -1026,8 +1024,7 @@ spec: is required. Local is the default setting. properties: local: - description: LocalRegistryConfig configures the deployed registry - service + description: LocalRegistryConfig configures the registry service properties: persistence: description: RegistryPersistence configures the persistence @@ -3316,7 +3313,7 @@ spec: type: string services: description: FeatureStoreServices defines the desired feast services. - An ephemeral registry is deployed by default. + An ephemeral onlineStore feature server is deployed by default. properties: deploymentStrategy: description: DeploymentStrategy describes how to replace existing @@ -3352,8 +3349,7 @@ spec: description: Disable the 'feast repo initialization' initContainer type: boolean offlineStore: - description: OfflineStore configures the deployed offline - store service + description: OfflineStore configures the offline store service properties: persistence: description: OfflineStorePersistence configures the persistence @@ -3800,8 +3796,7 @@ spec: type: object type: object onlineStore: - description: OnlineStore configures the deployed online store - service + description: OnlineStore configures the online store service properties: persistence: description: OnlineStorePersistence configures the persistence @@ -4268,8 +4263,8 @@ spec: selection is required. Local is the default setting. properties: local: - description: LocalRegistryConfig configures the deployed - registry service + description: LocalRegistryConfig configures the registry + service properties: persistence: description: RegistryPersistence configures the persistence diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_all_servers.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_all_servers.yaml index ccaeb31db25..0d9d744a678 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_all_servers.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_all_servers.yaml @@ -5,8 +5,9 @@ metadata: spec: feastProject: my_project services: - onlineStore: - server: {} offlineStore: server: {} + registry: + local: + server: {} ui: {} 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 bcecc33a3e4..e66b7fc3283 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_db_persistence.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_db_persistence.yaml @@ -33,7 +33,7 @@ stringData: apiVersion: feast.dev/v1alpha1 kind: FeatureStore metadata: - name: example + name: sample-db-persistence namespace: test spec: feastProject: my_project @@ -44,6 +44,10 @@ spec: type: postgres secretRef: name: feast-data-stores + server: + envFrom: + - secretRef: + name: postgres-secret registry: local: persistence: @@ -51,7 +55,3 @@ spec: type: sql secretRef: name: feast-data-stores - server: - envFrom: - - secretRef: - name: postgres-secret diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_ephemeral_persistence.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_ephemeral_persistence.yaml deleted file mode 100644 index 512fed9d4c0..00000000000 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_ephemeral_persistence.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: feast.dev/v1alpha1 -kind: FeatureStore -metadata: - name: sample-ephemeral-persistence -spec: - feastProject: my_project - services: - onlineStore: - persistence: - file: - path: /data/online_store.db - offlineStore: - persistence: - file: - type: dask - registry: - local: - persistence: - file: - path: /data/registry.db diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_kubernetes_auth.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_kubernetes_auth.yaml index ed95b41cf47..6751be60e9c 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_kubernetes_auth.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_kubernetes_auth.yaml @@ -4,20 +4,6 @@ metadata: name: sample-kubernetes-auth spec: feastProject: my_project - services: - onlineStore: - persistence: - file: - path: /data/online_store.db - offlineStore: - persistence: - file: - type: dask - registry: - local: - persistence: - file: - path: /data/registry.db authz: kubernetes: roles: diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_objectstore_persistence.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_objectstore_persistence.yaml index 45f12a67a18..2146dabe85c 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_objectstore_persistence.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_objectstore_persistence.yaml @@ -5,14 +5,6 @@ metadata: spec: feastProject: my_project services: - onlineStore: - persistence: - file: - path: /data/online_store.db - offlineStore: - persistence: - file: - type: dask registry: local: persistence: diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_oidc_auth.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_oidc_auth.yaml index c70f172ded9..54660a5c232 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_oidc_auth.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_oidc_auth.yaml @@ -4,20 +4,6 @@ metadata: name: sample-oidc-auth spec: feastProject: my_project - services: - onlineStore: - persistence: - file: - path: /data/online_store.db - offlineStore: - persistence: - file: - type: dask - registry: - local: - persistence: - file: - path: /data/registry.db authz: oidc: secretRef: 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 deleted file mode 100644 index 7b9c5819646..00000000000 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_openshift_tls_disable.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# The "tls.disable = true" setting will disable the creation of TLS for the Feast services in an OpenShift environment. -apiVersion: feast.dev/v1alpha1 -kind: FeatureStore -metadata: - name: sample-services-tls-disable -spec: - feastProject: my_project - services: - onlineStore: - server: - tls: - disable: true - offlineStore: - server: - tls: - disable: true - registry: - local: - server: - tls: - disable: true - ui: - tls: - disable: true diff --git a/infra/feast-operator/config/samples/v1alpha1_featurestore_postgres_db_volumes_ssl.yaml b/infra/feast-operator/config/samples/v1alpha1_featurestore_postgres_db_volumes_ssl.yaml index bfef906aab8..5988a5e942c 100644 --- a/infra/feast-operator/config/samples/v1alpha1_featurestore_postgres_db_volumes_ssl.yaml +++ b/infra/feast-operator/config/samples/v1alpha1_featurestore_postgres_db_volumes_ssl.yaml @@ -37,7 +37,7 @@ stringData: apiVersion: feast.dev/v1alpha1 kind: FeatureStore metadata: - name: example + name: sample-db-ssl namespace: default spec: feastProject: postgres_tls_sample @@ -68,6 +68,14 @@ spec: type: postgres secretRef: name: feast-data-stores + server: + volumeMounts: + - name: postgres-certs + mountPath: /var/lib/postgresql/certs + readOnly: true + envFrom: + - secretRef: + name: postgres-secret registry: local: persistence: @@ -75,11 +83,3 @@ spec: type: sql secretRef: name: feast-data-stores - server: - volumeMounts: - - name: postgres-certs - mountPath: /var/lib/postgresql/certs - readOnly: true - envFrom: - - secretRef: - name: postgres-secret \ No newline at end of file diff --git a/infra/feast-operator/dist/install.yaml b/infra/feast-operator/dist/install.yaml index 3858cc3d4c6..2e2e3e279c2 100644 --- a/infra/feast-operator/dist/install.yaml +++ b/infra/feast-operator/dist/install.yaml @@ -97,7 +97,7 @@ spec: type: string services: description: FeatureStoreServices defines the desired feast services. - An ephemeral registry is deployed by default. + An ephemeral onlineStore feature server is deployed by default. properties: deploymentStrategy: description: DeploymentStrategy describes how to replace existing @@ -133,8 +133,7 @@ spec: description: Disable the 'feast repo initialization' initContainer type: boolean offlineStore: - description: OfflineStore configures the deployed offline store - service + description: OfflineStore configures the offline store service properties: persistence: description: OfflineStorePersistence configures the persistence @@ -574,8 +573,7 @@ spec: type: object type: object onlineStore: - description: OnlineStore configures the deployed online store - service + description: OnlineStore configures the online store service properties: persistence: description: OnlineStorePersistence configures the persistence @@ -1034,8 +1032,7 @@ spec: is required. Local is the default setting. properties: local: - description: LocalRegistryConfig configures the deployed registry - service + description: LocalRegistryConfig configures the registry service properties: persistence: description: RegistryPersistence configures the persistence @@ -3324,7 +3321,7 @@ spec: type: string services: description: FeatureStoreServices defines the desired feast services. - An ephemeral registry is deployed by default. + An ephemeral onlineStore feature server is deployed by default. properties: deploymentStrategy: description: DeploymentStrategy describes how to replace existing @@ -3360,8 +3357,7 @@ spec: description: Disable the 'feast repo initialization' initContainer type: boolean offlineStore: - description: OfflineStore configures the deployed offline - store service + description: OfflineStore configures the offline store service properties: persistence: description: OfflineStorePersistence configures the persistence @@ -3808,8 +3804,7 @@ spec: type: object type: object onlineStore: - description: OnlineStore configures the deployed online store - service + description: OnlineStore configures the online store service properties: persistence: description: OnlineStorePersistence configures the persistence @@ -4276,8 +4271,8 @@ spec: selection is required. Local is the default setting. properties: local: - description: LocalRegistryConfig configures the deployed - registry service + description: LocalRegistryConfig configures the registry + service properties: persistence: description: RegistryPersistence configures the persistence diff --git a/infra/feast-operator/docs/api/markdown/ref.md b/infra/feast-operator/docs/api/markdown/ref.md index a1eaa753d21..7a4fe04c599 100644 --- a/infra/feast-operator/docs/api/markdown/ref.md +++ b/infra/feast-operator/docs/api/markdown/ref.md @@ -97,7 +97,7 @@ _Appears in:_ -FeatureStoreServices defines the desired feast services. An ephemeral registry is deployed by default. +FeatureStoreServices defines the desired feast services. An ephemeral onlineStore feature server is deployed by default. _Appears in:_ - [FeatureStoreSpec](#featurestorespec) @@ -173,7 +173,7 @@ Important note: the operator cannot ensure that these roles will match the ones -LocalRegistryConfig configures the deployed registry service +LocalRegistryConfig configures the registry service _Appears in:_ - [Registry](#registry) @@ -188,7 +188,7 @@ _Appears in:_ -OfflineStore configures the deployed offline store service +OfflineStore configures the offline store service _Appears in:_ - [FeatureStoreServices](#featurestoreservices) @@ -264,7 +264,7 @@ _Appears in:_ -OnlineStore configures the deployed online store service +OnlineStore configures the online store service _Appears in:_ - [FeatureStoreServices](#featurestoreservices) @@ -341,7 +341,7 @@ _Appears in:_ #### PvcConfig -_Underlying type:_ `[struct{Ref *k8s.io/api/core/v1.LocalObjectReference "json:\"ref,omitempty\""; Create *PvcCreate "json:\"create,omitempty\""; MountPath string "json:\"mountPath\""}](#struct{ref-*k8sioapicorev1localobjectreference-"json:\"ref,omitempty\"";-create-*pvccreate-"json:\"create,omitempty\"";-mountpath-string-"json:\"mountpath\""})` + PvcConfig defines the settings for a persistent file store based on PVCs. We can refer to an existing PVC using the `Ref` field, or create a new one using the `Create` field. @@ -349,9 +349,36 @@ We can refer to an existing PVC using the `Ref` field, or create a new one using _Appears in:_ - [OfflineStoreFilePersistence](#offlinestorefilepersistence) - [OnlineStoreFilePersistence](#onlinestorefilepersistence) +- [RegistryFilePersistence](#registryfilepersistence) + +| Field | Description | +| --- | --- | +| `ref` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | Reference to an existing field | +| `create` _[PvcCreate](#pvccreate)_ | Settings for creating a new PVC | +| `mountPath` _string_ | MountPath within the container at which the volume should be mounted. +Must start by "/" and cannot contain ':'. | + + +#### PvcCreate +PvcCreate defines the immutable settings to create a new PVC mounted at the given path. +The PVC name is the same as the associated deployment & feast service name. + +_Appears in:_ +- [PvcConfig](#pvcconfig) + +| Field | Description | +| --- | --- | +| `accessModes` _[PersistentVolumeAccessMode](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#persistentvolumeaccessmode-v1-core) array_ | AccessModes k8s persistent volume access modes. Defaults to ["ReadWriteOnce"]. | +| `storageClassName` _string_ | StorageClassName is the name of an existing StorageClass to which this persistent volume belongs. Empty value +means that this volume does not belong to any StorageClass and the cluster default will be used. | +| `resources` _[VolumeResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#volumeresourcerequirements-v1-core)_ | Resources describes the storage resource requirements for a volume. +Default requested storage size depends on the associated service: +- 10Gi for offline store +- 5Gi for online store +- 5Gi for registry | #### Registry @@ -371,24 +398,34 @@ _Appears in:_ #### RegistryDBStorePersistence -_Underlying type:_ `[struct{Type string "json:\"type\""; SecretRef k8s.io/api/core/v1.LocalObjectReference "json:\"secretRef\""; SecretKeyName string "json:\"secretKeyName,omitempty\""}](#struct{type-string-"json:\"type\"";-secretref-k8sioapicorev1localobjectreference-"json:\"secretref\"";-secretkeyname-string-"json:\"secretkeyname,omitempty\""})` + RegistryDBStorePersistence configures the DB store persistence for the registry service _Appears in:_ - [RegistryPersistence](#registrypersistence) +| Field | Description | +| --- | --- | +| `type` _string_ | Type of the persistence type you want to use. | +| `secretRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. | +| `secretKeyName` _string_ | By default, the selected store "type" is used as the SecretKeyName | #### RegistryFilePersistence -_Underlying type:_ `[struct{Path string "json:\"path,omitempty\""; PvcConfig *PvcConfig "json:\"pvc,omitempty\""; S3AdditionalKwargs *map[string]string "json:\"s3_additional_kwargs,omitempty\""}](#struct{path-string-"json:\"path,omitempty\"";-pvcconfig-*pvcconfig-"json:\"pvc,omitempty\"";-s3additionalkwargs-*map[string]string-"json:\"s3_additional_kwargs,omitempty\""})` + RegistryFilePersistence configures the file-based persistence for the registry service _Appears in:_ - [RegistryPersistence](#registrypersistence) +| Field | Description | +| --- | --- | +| `path` _string_ | | +| `pvc` _[PvcConfig](#pvcconfig)_ | | +| `s3_additional_kwargs` _map[string]string_ | | #### RegistryPersistence 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 e4f5847583e..390c225f613 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 @@ -224,17 +224,13 @@ var _ = Describe("FeatureStore Controller - db storage services", func() { }, }, } - resource.Spec.Services.Registry = &feastdevv1alpha1.Registry{ - Local: &feastdevv1alpha1.LocalRegistryConfig{ - Persistence: &feastdevv1alpha1.RegistryPersistence{ - DBPersistence: &feastdevv1alpha1.RegistryDBStorePersistence{ - Type: string(registryType), - SecretRef: corev1.LocalObjectReference{ - Name: "registry-store-secret", - }, - SecretKeyName: "sql_custom_registry_key", - }, + resource.Spec.Services.Registry.Local.Persistence = &feastdevv1alpha1.RegistryPersistence{ + DBPersistence: &feastdevv1alpha1.RegistryDBStorePersistence{ + Type: string(registryType), + SecretRef: corev1.LocalObjectReference{ + Name: "registry-store-secret", }, + SecretKeyName: "sql_custom_registry_key", }, } 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 6de38263e75..a0c01c11449 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_ephemeral_test.go @@ -78,13 +78,9 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Path: onlineStorePath, }, } - resource.Spec.Services.Registry = &feastdevv1alpha1.Registry{ - Local: &feastdevv1alpha1.LocalRegistryConfig{ - Persistence: &feastdevv1alpha1.RegistryPersistence{ - FilePersistence: &feastdevv1alpha1.RegistryFilePersistence{ - Path: registryPath, - }, - }, + resource.Spec.Services.Registry.Local.Persistence = &feastdevv1alpha1.RegistryPersistence{ + FilePersistence: &feastdevv1alpha1.RegistryFilePersistence{ + Path: registryPath, }, } 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 418e57bb8e9..90b80c907d5 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_loglevel_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_loglevel_test.go @@ -194,8 +194,10 @@ var _ = Describe("FeatureStore Controller - Feast service LogLevel", func() { Expect(err).NotTo(HaveOccurred()) resource.Spec.Services = &feastdevv1alpha1.FeatureStoreServices{ - OnlineStore: &feastdevv1alpha1.OnlineStore{ - Server: &feastdevv1alpha1.ServerConfigs{}, + Registry: &feastdevv1alpha1.Registry{ + Local: &feastdevv1alpha1.LocalRegistryConfig{ + Server: &feastdevv1alpha1.ServerConfigs{}, + }, }, OfflineStore: &feastdevv1alpha1.OfflineStore{}, UI: &feastdevv1alpha1.ServerConfigs{}, 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 aed8db000e0..81dc15d8545 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go @@ -71,16 +71,12 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { if err != nil && errors.IsNotFound(err) { resource := createFeatureStoreResource(resourceName, image, pullPolicy, &[]corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}}, withEnvFrom()) - resource.Spec.Services.OnlineStore = nil + resource.Spec.Services.UI = nil resource.Spec.Services.OfflineStore = nil - resource.Spec.Services.Registry = &feastdevv1alpha1.Registry{ - Local: &feastdevv1alpha1.LocalRegistryConfig{ - Persistence: &feastdevv1alpha1.RegistryPersistence{ - FilePersistence: &feastdevv1alpha1.RegistryFilePersistence{ - Path: registryPath, - S3AdditionalKwargs: &s3AdditionalKwargs, - }, - }, + resource.Spec.Services.Registry.Local.Persistence = &feastdevv1alpha1.RegistryPersistence{ + FilePersistence: &feastdevv1alpha1.RegistryFilePersistence{ + Path: registryPath, + S3AdditionalKwargs: &s3AdditionalKwargs, }, } Expect(k8sClient.Create(ctx, resource)).To(Succeed()) @@ -128,7 +124,8 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(resource.Status.Applied.AuthzConfig).To(BeNil()) Expect(resource.Status.Applied.Services).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore).To(BeNil()) - Expect(resource.Status.Applied.Services.OnlineStore).To(BeNil()) + Expect(resource.Status.Applied.Services.OnlineStore).NotTo(BeNil()) + Expect(resource.Status.Applied.Services.UI).To(BeNil()) 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()) @@ -142,7 +139,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { 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()) + Expect(resource.Status.ServiceHostnames.OnlineStore).NotTo(BeEmpty()) Expect(resource.Status.ServiceHostnames.Registry).To(Equal(feast.GetFeastServiceName(services.RegistryFeastType) + "." + resource.Namespace + domain)) Expect(resource.Status.Conditions).NotTo(BeEmpty()) @@ -174,7 +171,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(cond).To(BeNil()) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.OnlineStoreReadyType) - Expect(cond).To(BeNil()) + Expect(cond).NotTo(BeNil()) Expect(resource.Status.Phase).To(Equal(feastdevv1alpha1.PendingPhase)) @@ -191,7 +188,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(1)) Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(2)) Expect(services.GetRegistryContainer(*deploy)).NotTo(BeNil()) - Expect(services.GetOnlineContainer(*deploy)).To(BeNil()) + Expect(services.GetOnlineContainer(*deploy)).NotTo(BeNil()) Expect(services.GetOfflineContainer(*deploy)).To(BeNil()) Expect(deploy.Spec.Template.Spec.Volumes).To(HaveLen(1)) Expect(deploy.Spec.Template.Spec.Containers[0].VolumeMounts).To(HaveLen(1)) @@ -286,7 +283,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(controllerutil.HasControllerReference(deploy)).To(BeTrue()) Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(2)) Expect(services.GetRegistryContainer(*deploy)).NotTo(BeNil()) - Expect(services.GetOnlineContainer(*deploy)).To(BeNil()) + Expect(services.GetOnlineContainer(*deploy)).NotTo(BeNil()) Expect(services.GetOfflineContainer(*deploy)).To(BeNil()) Expect(deploy.Spec.Template.Spec.Volumes).To(HaveLen(1)) Expect(deploy.Spec.Template.Spec.Containers[0].VolumeMounts).To(HaveLen(1)) @@ -325,6 +322,10 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { err = yaml.Unmarshal([]byte(cm.Data[services.FeatureStoreYamlCmKey]), repoConfigClient) Expect(err).NotTo(HaveOccurred()) clientConfig := feast.GetInitRepoConfig() + clientConfig.OnlineStore = services.OnlineStoreConfig{ + Type: services.OnlineRemoteConfigType, + Path: fmt.Sprintf("http://feast-%s-online.default.svc.cluster.local:80", resourceName), + } clientConfig.Registry = services.RegistryConfig{ RegistryType: services.RegistryRemoteConfigType, Path: fmt.Sprintf("feast-%s-registry.default.svc.cluster.local:80", resourceName), 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 bb795e8972c..ec40527ceae 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_pvc_test.go @@ -104,16 +104,12 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { }, }, } - resource.Spec.Services.Registry = &feastdevv1alpha1.Registry{ - Local: &feastdevv1alpha1.LocalRegistryConfig{ - Persistence: &feastdevv1alpha1.RegistryPersistence{ - FilePersistence: &feastdevv1alpha1.RegistryFilePersistence{ - Path: registryPath, - PvcConfig: &feastdevv1alpha1.PvcConfig{ - Create: &feastdevv1alpha1.PvcCreate{}, - MountPath: registryMountPath, - }, - }, + resource.Spec.Services.Registry.Local.Persistence = &feastdevv1alpha1.RegistryPersistence{ + FilePersistence: &feastdevv1alpha1.RegistryFilePersistence{ + Path: registryPath, + PvcConfig: &feastdevv1alpha1.PvcConfig{ + Create: &feastdevv1alpha1.PvcCreate{}, + MountPath: registryMountPath, }, }, } diff --git a/infra/feast-operator/internal/controller/featurestore_controller_test.go b/infra/feast-operator/internal/controller/featurestore_controller_test.go index f1259162c0f..23d93903d16 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_test.go @@ -156,21 +156,17 @@ var _ = Describe("FeatureStore Controller", func() { Expect(resource.Status.FeastVersion).To(Equal(feastversion.FeastVersion)) Expect(resource.Status.ClientConfigMap).To(Equal(feast.GetFeastServiceName(services.ClientFeastType))) Expect(resource.Status.ServiceHostnames.OfflineStore).To(BeEmpty()) - Expect(resource.Status.ServiceHostnames.OnlineStore).To(BeEmpty()) + Expect(resource.Status.ServiceHostnames.Registry).To(BeEmpty()) Expect(resource.Status.ServiceHostnames.UI).To(BeEmpty()) - Expect(resource.Status.ServiceHostnames.Registry).To(Equal(feast.GetFeastServiceName(services.RegistryFeastType) + "." + resource.Namespace + ".svc.cluster.local:80")) + Expect(resource.Status.ServiceHostnames.OnlineStore).To(Equal(feast.GetFeastServiceName(services.OnlineFeastType) + "." + resource.Namespace + ".svc.cluster.local:80")) Expect(resource.Status.Applied.FeastProject).To(Equal(resource.Spec.FeastProject)) Expect(resource.Status.Applied.AuthzConfig).To(BeNil()) Expect(resource.Status.Applied.Services).NotTo(BeNil()) Expect(resource.Status.Applied.Services.OfflineStore).To(BeNil()) - Expect(resource.Status.Applied.Services.OnlineStore).To(BeNil()) + Expect(resource.Status.Applied.Services.Registry).To(BeNil()) Expect(resource.Status.Applied.Services.UI).To(BeNil()) - 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.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.Registry).To(BeNil()) + Expect(resource.Status.Applied.Services.OnlineStore).NotTo(BeNil()) Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ReadyType) @@ -182,12 +178,12 @@ var _ = Describe("FeatureStore Controller", func() { cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) - cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) + cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.OnlineStoreReadyType) Expect(cond).ToNot(BeNil()) Expect(cond.Status).To(Equal(metav1.ConditionTrue)) Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) - Expect(cond.Type).To(Equal(feastdevv1alpha1.RegistryReadyType)) - Expect(cond.Message).To(Equal(feastdevv1alpha1.RegistryReadyMessage)) + Expect(cond.Type).To(Equal(feastdevv1alpha1.OnlineStoreReadyType)) + Expect(cond.Message).To(Equal(feastdevv1alpha1.OnlineStoreReadyMessage)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ClientReadyType) Expect(cond).ToNot(BeNil()) @@ -213,13 +209,13 @@ var _ = Describe("FeatureStore Controller", func() { svc := &corev1.Service{} err = k8sClient.Get(ctx, types.NamespacedName{ - Name: feast.GetFeastServiceName(services.RegistryFeastType), + Name: feast.GetFeastServiceName(services.OnlineFeastType), Namespace: resource.Namespace, }, svc) Expect(err).NotTo(HaveOccurred()) Expect(controllerutil.HasControllerReference(svc)).To(BeTrue()) - Expect(svc.Spec.Ports[0].TargetPort).To(Equal(intstr.FromInt(int(services.FeastServiceConstants[services.RegistryFeastType].TargetHttpPort)))) + Expect(svc.Spec.Ports[0].TargetPort).To(Equal(intstr.FromInt(int(services.FeastServiceConstants[services.OnlineFeastType].TargetHttpPort)))) }) It("should properly encode a feature_store.yaml config", func() { @@ -286,9 +282,9 @@ var _ = Describe("FeatureStore Controller", func() { err = yaml.Unmarshal([]byte(cm.Data[services.FeatureStoreYamlCmKey]), repoConfigClient) Expect(err).NotTo(HaveOccurred()) clientConfig := feast.GetInitRepoConfig() - clientConfig.Registry = services.RegistryConfig{ - RegistryType: services.RegistryRemoteConfigType, - Path: "feast-test-resource-registry.default.svc.cluster.local:80", + clientConfig.OnlineStore = services.OnlineStoreConfig{ + Type: services.OnlineRemoteConfigType, + Path: "http://feast-test-resource-online.default.svc.cluster.local:80", } Expect(repoConfigClient).To(Equal(&clientConfig)) @@ -372,7 +368,7 @@ var _ = Describe("FeatureStore Controller", func() { Expect(controllerutil.HasControllerReference(deploy)).To(BeFalse()) svc := &corev1.Service{} - name := feast.GetFeastServiceName(services.RegistryFeastType) + name := feast.GetFeastServiceName(services.OnlineFeastType) err = k8sClient.Get(ctx, types.NamespacedName{ Name: name, Namespace: resource.Namespace, @@ -404,11 +400,11 @@ var _ = Describe("FeatureStore Controller", func() { cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.AuthorizationReadyType) Expect(cond).To(BeNil()) - cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.RegistryReadyType) + cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.OnlineStoreReadyType) Expect(cond).ToNot(BeNil()) Expect(cond.Status).To(Equal(metav1.ConditionTrue)) Expect(cond.Reason).To(Equal(feastdevv1alpha1.ReadyReason)) - Expect(cond.Type).To(Equal(feastdevv1alpha1.RegistryReadyType)) + Expect(cond.Type).To(Equal(feastdevv1alpha1.OnlineStoreReadyType)) cond = apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1alpha1.ClientReadyType) Expect(cond).ToNot(BeNil()) @@ -900,8 +896,8 @@ var _ = Describe("FeatureStore Controller", func() { Expect(err).NotTo(HaveOccurred()) Expect(svcList.Items).To(HaveLen(4)) - // disable the Online Store service - resource.Spec.Services.OnlineStore = nil + // disable the UI Store service + resource.Spec.Services.UI = nil err = k8sClient.Update(ctx, resource) Expect(err).NotTo(HaveOccurred()) @@ -1244,8 +1240,6 @@ var _ = Describe("FeatureStore Controller", func() { err := k8sClient.Get(ctx, typeNamespacedName, resource) Expect(err).NotTo(HaveOccurred()) - Expect(resource.Spec.Services.Registry).To(BeNil()) - resource.Spec.Services.Registry = &feastdevv1alpha1.Registry{} err = k8sClient.Update(ctx, resource) Expect(err).To(HaveOccurred()) 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 c1d0cd0f0e9..dcf684c7733 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 @@ -128,6 +128,11 @@ func createFeatureStoreResource(resourceName string, image string, pullPolicy co }, }, }, + Registry: &feastdevv1alpha1.Registry{ + Local: &feastdevv1alpha1.LocalRegistryConfig{ + Server: &feastdevv1alpha1.ServerConfigs{}, + }, + }, UI: &feastdevv1alpha1.ServerConfigs{ ContainerConfigs: feastdevv1alpha1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1alpha1.DefaultCtrConfigs{ 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 8a4c2a61239..a346ac72e80 100644 --- a/infra/feast-operator/internal/controller/services/repo_config_test.go +++ b/infra/feast-operator/internal/controller/services/repo_config_test.go @@ -93,8 +93,8 @@ var _ = Describe("Repo Config", func() { } ApplyDefaultsToStatus(featureStore) appliedServices := featureStore.Status.Applied.Services - Expect(appliedServices.OnlineStore).To(BeNil()) - Expect(appliedServices.OnlineStore).To(BeNil()) + Expect(appliedServices.OnlineStore).NotTo(BeNil()) + Expect(appliedServices.Registry.Local).NotTo(BeNil()) repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret) Expect(err).NotTo(HaveOccurred()) @@ -367,12 +367,15 @@ func minimalFeatureStore() *feastdevv1alpha1.FeatureStore { func minimalFeatureStoreWithAllServers() *feastdevv1alpha1.FeatureStore { feast := minimalFeatureStore() + // onlineStore configured by default feast.Spec.Services = &feastdevv1alpha1.FeatureStoreServices{ OfflineStore: &feastdevv1alpha1.OfflineStore{ Server: &feastdevv1alpha1.ServerConfigs{}, }, - OnlineStore: &feastdevv1alpha1.OnlineStore{ - Server: &feastdevv1alpha1.ServerConfigs{}, + Registry: &feastdevv1alpha1.Registry{ + Local: &feastdevv1alpha1.LocalRegistryConfig{ + Server: &feastdevv1alpha1.ServerConfigs{}, + }, }, UI: &feastdevv1alpha1.ServerConfigs{}, } diff --git a/infra/feast-operator/internal/controller/services/services.go b/infra/feast-operator/internal/controller/services/services.go index ece43074599..9380415965f 100644 --- a/infra/feast-operator/internal/controller/services/services.go +++ b/infra/feast-operator/internal/controller/services/services.go @@ -431,8 +431,8 @@ func (feast *FeastServices) setContainer(containers *[]corev1.Container, feastTy func (feast *FeastServices) mountUserDefinedVolumes(podSpec *corev1.PodSpec) { var volumes []corev1.Volume - if feast.Handler.FeatureStore.Spec.Services != nil { - volumes = feast.Handler.FeatureStore.Spec.Services.Volumes + if feast.Handler.FeatureStore.Status.Applied.Services != nil { + volumes = feast.Handler.FeatureStore.Status.Applied.Services.Volumes } if len(volumes) > 0 { podSpec.Volumes = append(podSpec.Volumes, volumes...) @@ -440,28 +440,8 @@ func (feast *FeastServices) mountUserDefinedVolumes(podSpec *corev1.PodSpec) { } func (feast *FeastServices) getVolumeMounts(feastType FeastServiceType) (volumeMounts []corev1.VolumeMount) { - appliedServices := feast.Handler.FeatureStore.Status.Applied.Services - if appliedServices == nil { - return []corev1.VolumeMount{} // Return an empty slice to avoid nil issues - } - - switch feastType { - case OfflineFeastType: - if feast.isOfflineServer() { - return appliedServices.OfflineStore.Server.VolumeMounts - } - case OnlineFeastType: - if feast.isOnlineServer() { - return appliedServices.OnlineStore.Server.VolumeMounts - } - case RegistryFeastType: - if feast.isRegistryServer() { - return appliedServices.Registry.Local.Server.VolumeMounts - } - case UIFeastType: - if feast.isUiServer() { - return appliedServices.UI.VolumeMounts - } + if serviceConfigs := feast.getServerConfigs(feastType); serviceConfigs != nil { + return serviceConfigs.VolumeMounts } return []corev1.VolumeMount{} // Default empty slice } @@ -787,7 +767,7 @@ func (feast *FeastServices) isRemoteHostnameRegistry() bool { func (feast *FeastServices) isOfflineServer() bool { return feast.isOfflineStore() && - feast.Handler.FeatureStore.Spec.Services.OfflineStore.Server != nil + feast.Handler.FeatureStore.Status.Applied.Services.OfflineStore.Server != nil } func (feast *FeastServices) isOfflineStore() bool { @@ -797,7 +777,7 @@ func (feast *FeastServices) isOfflineStore() bool { func (feast *FeastServices) isOnlineServer() bool { return feast.isOnlineStore() && - feast.Handler.FeatureStore.Spec.Services.OnlineStore.Server != nil + feast.Handler.FeatureStore.Status.Applied.Services.OnlineStore.Server != nil } func (feast *FeastServices) isOnlineStore() bool { diff --git a/infra/feast-operator/internal/controller/services/tls.go b/infra/feast-operator/internal/controller/services/tls.go index ae3819ab6b9..03a26a9031d 100644 --- a/infra/feast-operator/internal/controller/services/tls.go +++ b/infra/feast-operator/internal/controller/services/tls.go @@ -126,7 +126,11 @@ func (feast *FeastServices) offlineOpenshiftTls() bool { // True if running in an openshift cluster and Tls not configured in the service Spec func (feast *FeastServices) onlineOpenshiftTls() bool { return isOpenShift && - feast.isOnlineServer() && feast.Handler.FeatureStore.Spec.Services.OnlineStore.Server.TLS == nil + feast.isOnlineServer() && + (feast.Handler.FeatureStore.Spec.Services == nil || + feast.Handler.FeatureStore.Spec.Services.OnlineStore == nil || + feast.Handler.FeatureStore.Spec.Services.OnlineStore.Server == nil || + feast.Handler.FeatureStore.Spec.Services.OnlineStore.Server.TLS == nil) } // True if running in an openshift cluster and Tls not configured in the service Spec @@ -138,12 +142,7 @@ func (feast *FeastServices) uiOpenshiftTls() bool { // True if running in an openshift cluster and Tls not configured in the service Spec func (feast *FeastServices) localRegistryOpenshiftTls() bool { return isOpenShift && - 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.Server == nil || - feast.Handler.FeatureStore.Spec.Services.Registry.Local.Server.TLS == nil) + feast.isRegistryServer() && 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 diff --git a/infra/feast-operator/internal/controller/services/tls_test.go b/infra/feast-operator/internal/controller/services/tls_test.go index eeae0de3ebc..04925ff02ee 100644 --- a/infra/feast-operator/internal/controller/services/tls_test.go +++ b/infra/feast-operator/internal/controller/services/tls_test.go @@ -93,8 +93,8 @@ var _ = Describe("TLS Config", func() { Expect(tls).To(BeNil()) Expect(tls.IsTLS()).To(BeFalse()) tls = feast.getTlsConfigs(OnlineFeastType) - Expect(tls).To(BeNil()) - Expect(tls.IsTLS()).To(BeFalse()) + Expect(tls).NotTo(BeNil()) + Expect(tls.IsTLS()).To(BeTrue()) tls = feast.getTlsConfigs(UIFeastType) Expect(tls).To(BeNil()) Expect(tls.IsTLS()).To(BeFalse()) @@ -108,7 +108,7 @@ var _ = Describe("TLS Config", func() { Expect(feast.remoteRegistryTls()).To(BeFalse()) Expect(feast.localRegistryTls()).To(BeTrue()) Expect(feast.isOpenShiftTls(OfflineFeastType)).To(BeFalse()) - Expect(feast.isOpenShiftTls(OnlineFeastType)).To(BeFalse()) + Expect(feast.isOpenShiftTls(OnlineFeastType)).To(BeTrue()) Expect(feast.isOpenShiftTls(UIFeastType)).To(BeFalse()) Expect(feast.isOpenShiftTls(RegistryFeastType)).To(BeTrue()) @@ -229,8 +229,12 @@ var _ = Describe("TLS Config", func() { // all services w/ tls and in an openshift cluster feast.Handler.FeatureStore = minimalFeatureStoreWithAllServers() disable := true - feast.Handler.FeatureStore.Spec.Services.OnlineStore.Server.TLS = &feastdevv1alpha1.TlsConfigs{ - Disable: &disable, + feast.Handler.FeatureStore.Spec.Services.OnlineStore = &feastdevv1alpha1.OnlineStore{ + Server: &feastdevv1alpha1.ServerConfigs{ + TLS: &feastdevv1alpha1.TlsConfigs{ + Disable: &disable, + }, + }, } feast.Handler.FeatureStore.Spec.Services.UI.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 c4a8f89c672..82dc65e14b5 100644 --- a/infra/feast-operator/internal/controller/services/util.go +++ b/infra/feast-operator/internal/controller/services/util.go @@ -95,38 +95,35 @@ func ApplyDefaultsToStatus(cr *feastdevv1alpha1.FeatureStore) { } services := applied.Services - // default to registry service deployment - if services.Registry == nil { - services.Registry = &feastdevv1alpha1.Registry{} - } - // if remote registry not set, proceed w/ local registry defaults - if services.Registry.Remote == nil { - // if local registry not set, apply an empty pointer struct - if services.Registry.Local == nil { - services.Registry.Local = &feastdevv1alpha1.LocalRegistryConfig{} - } - if services.Registry.Local.Persistence == nil { - services.Registry.Local.Persistence = &feastdevv1alpha1.RegistryPersistence{} - } - - if services.Registry.Local.Persistence.DBPersistence == nil { - if services.Registry.Local.Persistence.FilePersistence == nil { - services.Registry.Local.Persistence.FilePersistence = &feastdevv1alpha1.RegistryFilePersistence{} + if services.Registry != nil { + // if remote registry not set, proceed w/ local registry defaults + if services.Registry.Remote == nil { + // if local registry not set, apply an empty pointer struct + if services.Registry.Local == nil { + services.Registry.Local = &feastdevv1alpha1.LocalRegistryConfig{} } - - if len(services.Registry.Local.Persistence.FilePersistence.Path) == 0 { - services.Registry.Local.Persistence.FilePersistence.Path = defaultRegistryPath(cr) + if services.Registry.Local.Persistence == nil { + services.Registry.Local.Persistence = &feastdevv1alpha1.RegistryPersistence{} } - ensurePVCDefaults(services.Registry.Local.Persistence.FilePersistence.PvcConfig, RegistryFeastType) - } + if services.Registry.Local.Persistence.DBPersistence == nil { + if services.Registry.Local.Persistence.FilePersistence == nil { + services.Registry.Local.Persistence.FilePersistence = &feastdevv1alpha1.RegistryFilePersistence{} + } - if services.Registry.Local.Server == nil { - services.Registry.Local.Server = &feastdevv1alpha1.ServerConfigs{} + if len(services.Registry.Local.Persistence.FilePersistence.Path) == 0 { + services.Registry.Local.Persistence.FilePersistence.Path = defaultRegistryPath(cr) + } + + ensurePVCDefaults(services.Registry.Local.Persistence.FilePersistence.PvcConfig, RegistryFeastType) + } + + if services.Registry.Local.Server != nil { + 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 } - 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 } if services.OfflineStore != nil { @@ -151,27 +148,31 @@ func ApplyDefaultsToStatus(cr *feastdevv1alpha1.FeatureStore) { } } - if services.OnlineStore != nil { - if services.OnlineStore.Persistence == nil { - services.OnlineStore.Persistence = &feastdevv1alpha1.OnlineStorePersistence{} - } - - if services.OnlineStore.Persistence.DBPersistence == nil { - if services.OnlineStore.Persistence.FilePersistence == nil { - services.OnlineStore.Persistence.FilePersistence = &feastdevv1alpha1.OnlineStoreFilePersistence{} - } - - if len(services.OnlineStore.Persistence.FilePersistence.Path) == 0 { - services.OnlineStore.Persistence.FilePersistence.Path = defaultOnlineStorePath(cr) - } + // default to onlineStore service deployment + if services.OnlineStore == nil { + services.OnlineStore = &feastdevv1alpha1.OnlineStore{} + } + if services.OnlineStore.Persistence == nil { + services.OnlineStore.Persistence = &feastdevv1alpha1.OnlineStorePersistence{} + } - ensurePVCDefaults(services.OnlineStore.Persistence.FilePersistence.PvcConfig, OnlineFeastType) + if services.OnlineStore.Persistence.DBPersistence == nil { + if services.OnlineStore.Persistence.FilePersistence == nil { + services.OnlineStore.Persistence.FilePersistence = &feastdevv1alpha1.OnlineStoreFilePersistence{} } - if services.OnlineStore.Server != nil { - setDefaultCtrConfigs(&services.OnlineStore.Server.ContainerConfigs.DefaultCtrConfigs) + if len(services.OnlineStore.Persistence.FilePersistence.Path) == 0 { + services.OnlineStore.Persistence.FilePersistence.Path = defaultOnlineStorePath(cr) } + + ensurePVCDefaults(services.OnlineStore.Persistence.FilePersistence.PvcConfig, OnlineFeastType) } + + if services.OnlineStore.Server == nil { + services.OnlineStore.Server = &feastdevv1alpha1.ServerConfigs{} + } + 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 3d707fbafd9..9edf1dd9664 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,8 +5,9 @@ metadata: spec: feastProject: my_project services: - onlineStore: - server: {} offlineStore: server: {} + registry: + local: + 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 73f8880dc14..9746e3819a5 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,6 @@ metadata: spec: feastProject: my_project services: - onlineStore: - server: {} offlineStore: server: {} ui: {} From 11e45482b0cace1f3c3a0ddc567a8a1172d6792a Mon Sep 17 00:00:00 2001 From: Tommy Hughes IV Date: Fri, 14 Feb 2025 15:19:13 -0600 Subject: [PATCH 25/30] fix: Operator - resolve infinite reconciler loop in authz controller (#5056) resolve infinite reconciler loop in authz controller Signed-off-by: Tommy Hughes --- infra/feast-operator/internal/controller/authz/authz.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infra/feast-operator/internal/controller/authz/authz.go b/infra/feast-operator/internal/controller/authz/authz.go index 8596d993899..122e9f69457 100644 --- a/infra/feast-operator/internal/controller/authz/authz.go +++ b/infra/feast-operator/internal/controller/authz/authz.go @@ -134,11 +134,11 @@ func (authz *FeastAuthorization) initFeastRoleBinding() *rbacv1.RoleBinding { func (authz *FeastAuthorization) setFeastRoleBinding(roleBinding *rbacv1.RoleBinding) error { roleBinding.Labels = authz.getLabels() - roleBinding.Subjects = append(roleBinding.Subjects, rbacv1.Subject{ + roleBinding.Subjects = []rbacv1.Subject{{ Kind: rbacv1.ServiceAccountKind, Name: services.GetFeastName(authz.Handler.FeatureStore), Namespace: authz.Handler.FeatureStore.Namespace, - }) + }} roleBinding.RoleRef = rbacv1.RoleRef{ APIGroup: rbacv1.GroupName, Kind: "Role", From a13fa9bd18be94b349954e5db66fd30ba4db1d1e Mon Sep 17 00:00:00 2001 From: lokeshrangineni <19699092+lokeshrangineni@users.noreply.github.com> Date: Fri, 14 Feb 2025 19:40:37 -0500 Subject: [PATCH 26/30] fix: Fixing the release workflow to refresh the stable branch when the release is not running in the dry run mode. (#5057) Fixing the release workflow to refresh the stable branch when the release is not running in the dry run mode. Signed-off-by: lrangine <19699092+lokeshrangineni@users.noreply.github.com> --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 09fe7152dcf..1ae75382905 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -183,6 +183,7 @@ jobs: update_stable_branch: name: Update Stable Branch after release + if: github.event.inputs.dry_run == 'false' runs-on: ubuntu-latest needs: release env: From 0fffe211be9db18d318634f47bc9401fd6e218a0 Mon Sep 17 00:00:00 2001 From: Francisco Arceo Date: Sat, 15 Feb 2025 23:59:12 -0500 Subject: [PATCH 27/30] feat: Add SQLite retrieve_online_documents_v2 (#5032) * feat: Add SQLite Offline store Signed-off-by: Francisco Javier Arceo * removing commented out thing Signed-off-by: Francisco Javier Arceo * updated entity key serialization Signed-off-by: Francisco Javier Arceo * updated Signed-off-by: Francisco Javier Arceo * reverting some changes Signed-off-by: Francisco Javier Arceo * updated Signed-off-by: Francisco Javier Arceo * fixed implementation Signed-off-by: Francisco Javier Arceo * updated docs Signed-off-by: Francisco Javier Arceo --------- Signed-off-by: Francisco Javier Arceo --- docs/reference/alpha-vector-database.md | 18 +- .../feast/infra/online_stores/sqlite.py | 155 ++++++++++++++++-- .../online_store/test_online_retrieval.py | 63 +++++++ 3 files changed, 211 insertions(+), 25 deletions(-) diff --git a/docs/reference/alpha-vector-database.md b/docs/reference/alpha-vector-database.md index 216289f1949..a16baf2d7f6 100644 --- a/docs/reference/alpha-vector-database.md +++ b/docs/reference/alpha-vector-database.md @@ -7,14 +7,14 @@ Vector database allows user to store and retrieve embeddings. Feast provides gen ## Integration Below are supported vector databases and implemented features: -| Vector Database | Retrieval | Indexing | V2 Support* | -|-----------------|-----------|----------|-------------| -| Pgvector | [x] | [ ] | [] | -| Elasticsearch | [x] | [x] | [] | -| Milvus | [x] | [x] | [x] | -| Faiss | [ ] | [ ] | [] | -| SQLite | [x] | [ ] | [] | -| Qdrant | [x] | [x] | [] | +| Vector Database | Retrieval | Indexing | V2 Support* | Online Read | +|-----------------|-----------|----------|-------------|-------------| +| Pgvector | [x] | [ ] | [] | [] | +| Elasticsearch | [x] | [x] | [] | [] | +| Milvus | [x] | [x] | [x] | [x] | +| Faiss | [ ] | [ ] | [] | [] | +| SQLite | [x] | [ ] | [x] | [x] | +| Qdrant | [x] | [x] | [] | [] | *Note: V2 Support means the SDK supports retrieval of features along with vector embeddings from vector similarity search. @@ -30,7 +30,7 @@ Beyond that, we will then have `retrieve_online_documents` and `retrieve_online_ backwards compatibility and the adopt industry standard naming conventions. {% endhint %} -**Note**: Milvus implements the v2 `retrieve_online_documents_v2` method in the SDK. This will be the longer-term solution so that Data Scientists can easily enable vector similarity search by just flipping a flag. +**Note**: Milvus and SQLite implement the v2 `retrieve_online_documents_v2` method in the SDK. This will be the longer-term solution so that Data Scientists can easily enable vector similarity search by just flipping a flag. ## Examples diff --git a/sdk/python/feast/infra/online_stores/sqlite.py b/sdk/python/feast/infra/online_stores/sqlite.py index 23b4f6db3a3..945ec965fc9 100644 --- a/sdk/python/feast/infra/online_stores/sqlite.py +++ b/sdk/python/feast/infra/online_stores/sqlite.py @@ -26,6 +26,7 @@ from feast.feature_view import FeatureView from feast.infra.infra_object import SQLITE_INFRA_OBJECT_CLASS_TYPE, InfraObject from feast.infra.key_encoding_utils import ( + deserialize_entity_key, serialize_entity_key, serialize_f32, ) @@ -91,6 +92,9 @@ class SqliteOnlineStoreConfig(FeastConfigBaseModel, VectorStoreConfig): path: StrictStr = "data/online.db" """ (optional) Path to sqlite db """ + vector_enabled: bool = False + vector_len: Optional[int] = None + class SqliteOnlineStore(OnlineStore): """ @@ -116,14 +120,12 @@ def _get_db_path(config: RepoConfig) -> str: return db_path def _get_conn(self, config: RepoConfig): + enable_sqlite_vec = ( + sys.version_info[0:2] == (3, 10) and config.online_store.vector_enabled + ) if not self._conn: db_path = self._get_db_path(config) - self._conn = _initialize_conn(db_path) - if sys.version_info[0:2] == (3, 10) and config.online_store.vector_enabled: - import sqlite_vec # noqa: F401 - - self._conn.enable_load_extension(True) # type: ignore - sqlite_vec.load(self._conn) + self._conn = _initialize_conn(db_path, enable_sqlite_vec) return self._conn @@ -370,7 +372,7 @@ def retrieve_online_documents( cur.execute( f""" - CREATE VIRTUAL TABLE vec_example using vec0( + CREATE VIRTUAL TABLE vec_table using vec0( vector_value float[{config.online_store.vector_len}] ); """ @@ -379,13 +381,13 @@ def retrieve_online_documents( # Currently I can only insert the embedding value without crashing SQLite, will report a bug cur.execute( f""" - INSERT INTO vec_example(rowid, vector_value) + INSERT INTO vec_table(rowid, vector_value) select rowid, vector_value from {table_name} """ ) cur.execute( """ - INSERT INTO vec_example(rowid, vector_value) + INSERT INTO vec_table(rowid, vector_value) VALUES (?, ?) """, (0, query_embedding_bin), @@ -406,7 +408,7 @@ def retrieve_online_documents( rowid, vector_value, distance - from vec_example + from vec_table where vector_value match ? order by distance limit ? @@ -444,18 +446,139 @@ def retrieve_online_documents( return result + def retrieve_online_documents_v2( + self, + config: RepoConfig, + table: FeatureView, + requested_features: List[str], + query: List[float], + top_k: int, + distance_metric: Optional[str] = None, + ) -> List[ + Tuple[ + Optional[datetime], + Optional[EntityKeyProto], + Optional[Dict[str, ValueProto]], + ] + ]: + """ + Retrieve documents using vector similarity search. + Args: + config: Feast configuration object + table: FeatureView object as the table to search + requested_features: List of requested features to retrieve + query: Query embedding to search for + top_k: Number of items to return + distance_metric: Distance metric to use (optional) + Returns: + List of tuples containing the event timestamp, entity key, and feature values + """ + online_store = config.online_store + if not isinstance(online_store, SqliteOnlineStoreConfig): + raise ValueError("online_store must be SqliteOnlineStoreConfig") + if not online_store.vector_enabled: + raise ValueError("Vector search is not enabled in the online store config") + + conn = self._get_conn(config) + cur = conn.cursor() + + online_store = config.online_store + if not isinstance(online_store, SqliteOnlineStoreConfig): + raise ValueError("online_store must be SqliteOnlineStoreConfig") + if not online_store.vector_len: + raise ValueError("vector_len is not configured in the online store config") + query_embedding_bin = serialize_f32(query, online_store.vector_len) # type: ignore + table_name = _table_id(config.project, table) + + cur.execute( + f""" + CREATE VIRTUAL TABLE IF NOT EXISTS vec_table using vec0( + vector_value float[{online_store.vector_len}] + ); + """ + ) + + cur.execute( + f""" + INSERT INTO vec_table(rowid, vector_value) + select rowid, vector_value from {table_name} + """ + ) + + cur.execute( + f""" + select + fv.entity_key, + fv.feature_name, + fv.value, + f.distance, + fv.event_ts, + fv.created_ts + from ( + select + rowid, + vector_value, + distance + from vec_table + where vector_value match ? + order by distance + limit ? + ) f + left join {table_name} fv + on f.rowid = fv.rowid + where fv.feature_name in ({",".join(["?" for _ in requested_features])}) + """, + ( + query_embedding_bin, + top_k, + *[f.split(":")[-1] for f in requested_features], + ), + ) + + rows = cur.fetchall() + result: List[ + Tuple[ + Optional[datetime], + Optional[EntityKeyProto], + Optional[Dict[str, ValueProto]], + ] + ] = [] + + for entity_key, feature_name, value_bin, distance, event_ts, created_ts in rows: + val = ValueProto() + val.ParseFromString(value_bin) + entity_key_proto = None + if entity_key: + entity_key_proto = deserialize_entity_key( + entity_key, + entity_key_serialization_version=config.entity_key_serialization_version, + ) + res = {feature_name: val} + res["distance"] = ValueProto(float_val=distance) + result.append((event_ts, entity_key_proto, res)) + + return result + -def _initialize_conn(db_path: str): - try: - import sqlite_vec # noqa: F401 - except ModuleNotFoundError: - logging.warning("Cannot use sqlite_vec for vector search") +def _initialize_conn( + db_path: str, enable_sqlite_vec: bool = False +) -> sqlite3.Connection: Path(db_path).parent.mkdir(exist_ok=True) - return sqlite3.connect( + db = sqlite3.connect( db_path, detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES, check_same_thread=False, ) + if enable_sqlite_vec: + try: + import sqlite_vec # noqa: F401 + except ModuleNotFoundError: + logging.warning("Cannot use sqlite_vec for vector search") + + db.enable_load_extension(True) + sqlite_vec.load(db) + + return db def _table_id(project: str, table: FeatureView) -> str: diff --git a/sdk/python/tests/unit/online_store/test_online_retrieval.py b/sdk/python/tests/unit/online_store/test_online_retrieval.py index 9d6b7f3d178..5e5a3104c13 100644 --- a/sdk/python/tests/unit/online_store/test_online_retrieval.py +++ b/sdk/python/tests/unit/online_store/test_online_retrieval.py @@ -753,6 +753,69 @@ def test_sqlite_vec_import() -> None: assert result == [(2, 2.39), (1, 2.39)] +@pytest.mark.skipif( + sys.version_info[0:2] != (3, 10), + reason="Only works on Python 3.10", +) +def test_sqlite_get_online_documents_v2() -> None: + """Test retrieving documents using v2 method with vector similarity search.""" + n = 10 + vector_length = 8 + runner = CliRunner() + with runner.local_repo( + get_example_repo("example_feature_repo_1.py"), "file" + ) as store: + store.config.online_store.vector_enabled = True + store.config.online_store.vector_len = vector_length + store.config.entity_key_serialization_version = 3 + document_embeddings_fv = store.get_feature_view(name="document_embeddings") + + provider = store._get_provider() + + # Create test data + item_keys = [ + EntityKeyProto( + join_keys=["item_id"], entity_values=[ValueProto(int64_val=i)] + ) + for i in range(n) + ] + data = [] + for item_key in item_keys: + data.append( + ( + item_key, + { + "Embeddings": ValueProto( + float_list_val=FloatListProto( + val=[float(x) for x in np.random.random(vector_length)] + ) + ) + }, + _utc_now(), + _utc_now(), + ) + ) + + provider.online_write_batch( + config=store.config, + table=document_embeddings_fv, + data=data, + progress=None, + ) + + # Test vector similarity search + query_embedding = [float(x) for x in np.random.random(vector_length)] + result = store.retrieve_online_documents_v2( + features=["document_embeddings:Embeddings"], + query=query_embedding, + top_k=3, + ).to_dict() + + assert "Embeddings" in result + assert "distance" in result + assert len(result["distance"]) == 3 + + @pytest.mark.skip(reason="Skipping this test as CI struggles with it") def test_local_milvus() -> None: import random From 6bf75166fe6966595faeec160a6708fa5715e9b1 Mon Sep 17 00:00:00 2001 From: Artem <58334441+wckdman@users.noreply.github.com> Date: Sun, 16 Feb 2025 16:05:59 +0100 Subject: [PATCH 28/30] refactor: Rework `get_online_features` helper functions (#5060) * rework _populate_response_from_feature_data Signed-off-by: Artem Petrov <58334441+wckdman@users.noreply.github.com> * rework _convert_rows_to_protobuf Signed-off-by: Artem Petrov <58334441+wckdman@users.noreply.github.com> * fix typing Signed-off-by: Artem Petrov <58334441+wckdman@users.noreply.github.com> --------- Signed-off-by: Artem Petrov <58334441+wckdman@users.noreply.github.com> --- sdk/python/feast/feature_store.py | 3 +- .../feast/infra/online_stores/online_store.py | 10 +- sdk/python/feast/utils.py | 137 +++++++++--------- .../tests/unit/test_unit_feature_store.py | 6 +- 4 files changed, 79 insertions(+), 77 deletions(-) diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index 0f092538cf0..f0bdc4c1f28 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -2018,7 +2018,7 @@ def _retrieve_from_online_store_v2( entity_key_dict[key] = [] entity_key_dict[key].append(python_value) - table_entity_values, idxs = utils._get_unique_entities_from_values( + table_entity_values, idxs, output_len = utils._get_unique_entities_from_values( entity_key_dict, ) @@ -2040,6 +2040,7 @@ def _retrieve_from_online_store_v2( full_feature_names=False, requested_features=features_to_request, table=table, + output_len=output_len, ) return OnlineResponse(online_features_response) diff --git a/sdk/python/feast/infra/online_stores/online_store.py b/sdk/python/feast/infra/online_stores/online_store.py index a86fdba4017..f5202b66f66 100644 --- a/sdk/python/feast/infra/online_stores/online_store.py +++ b/sdk/python/feast/infra/online_stores/online_store.py @@ -187,7 +187,7 @@ def get_online_features( for table, requested_features in grouped_refs: # Get the correct set of entity values with the correct join keys. - table_entity_values, idxs = utils._get_unique_entities( + table_entity_values, idxs, output_len = utils._get_unique_entities( table, join_key_values, entity_name_to_join_key_map, @@ -215,6 +215,7 @@ def get_online_features( full_feature_names, requested_features, table, + output_len, ) if requested_on_demand_feature_views: @@ -274,7 +275,7 @@ async def get_online_features_async( async def query_table(table, requested_features): # Get the correct set of entity values with the correct join keys. - table_entity_values, idxs = utils._get_unique_entities( + table_entity_values, idxs, output_len = utils._get_unique_entities( table, join_key_values, entity_name_to_join_key_map, @@ -290,7 +291,7 @@ async def query_table(table, requested_features): requested_features=requested_features, ) - return idxs, read_rows + return idxs, read_rows, output_len all_responses = await asyncio.gather( *[ @@ -299,7 +300,7 @@ async def query_table(table, requested_features): ] ) - for (idxs, read_rows), (table, requested_features) in zip( + for (idxs, read_rows, output_len), (table, requested_features) in zip( all_responses, grouped_refs ): feature_data = utils._convert_rows_to_protobuf( @@ -314,6 +315,7 @@ async def query_table(table, requested_features): full_feature_names, requested_features, table, + output_len, ) if requested_on_demand_feature_views: diff --git a/sdk/python/feast/utils.py b/sdk/python/feast/utils.py index 86cb08ec932..e64e38b143a 100644 --- a/sdk/python/feast/utils.py +++ b/sdk/python/feast/utils.py @@ -490,16 +490,28 @@ def _group_feature_refs( return fvs_result, odfvs_result -def apply_list_mapping( - lst: Iterable[Any], mapping_indexes: Iterable[List[int]] -) -> Iterable[Any]: - output_len = sum(len(item) for item in mapping_indexes) - output = [None] * output_len - for elem, destinations in zip(lst, mapping_indexes): +def construct_response_feature_vector( + values_vector: Iterable[Any], + statuses_vector: Iterable[Any], + timestamp_vector: Iterable[Any], + mapping_indexes: Iterable[List[int]], + output_len: int, +) -> GetOnlineFeaturesResponse.FeatureVector: + values_output: Iterable[Any] = [None] * output_len + statuses_output: Iterable[Any] = [None] * output_len + timestamp_output: Iterable[Any] = [None] * output_len + + for i, destinations in enumerate(mapping_indexes): for idx in destinations: - output[idx] = elem - - return output + values_output[idx] = values_vector[i] # type: ignore[index] + statuses_output[idx] = statuses_vector[i] # type: ignore[index] + timestamp_output[idx] = timestamp_vector[i] # type: ignore[index] + + return GetOnlineFeaturesResponse.FeatureVector( + values=values_output, + statuses=statuses_output, + event_timestamps=timestamp_output, + ) def _augment_response_with_on_demand_transforms( @@ -674,7 +686,7 @@ def _get_unique_entities( table: "FeatureView", join_key_values: Dict[str, List[ValueProto]], entity_name_to_join_key_map: Dict[str, str], -) -> Tuple[Tuple[Dict[str, ValueProto], ...], Tuple[List[int], ...]]: +) -> Tuple[Tuple[Dict[str, ValueProto], ...], Tuple[List[int], ...], int]: """Return the set of unique composite Entities for a Feature View and the indexes at which they appear. This method allows us to query the OnlineStore for data we need only once @@ -712,7 +724,7 @@ def _get_unique_entities( # If there are no rows, return empty tuples. if not rowise: - return (), () + return (), (), 0 # Sort rowise so that rows with the same join key values are adjacent. rowise.sort(key=lambda row: tuple(getattr(x, x.WhichOneof("val")) for x in row[1])) @@ -725,16 +737,16 @@ def _get_unique_entities( # If no groups were formed (should not happen for valid input), return empty tuples. if not groups: - return (), () + return (), (), 0 # Unpack the unique entities and their original row indexes. unique_entities, indexes = tuple(zip(*groups)) - return unique_entities, indexes + return unique_entities, indexes, len(rowise) def _get_unique_entities_from_values( table_entity_values: Dict[str, List[ValueProto]], -) -> Tuple[Tuple[Dict[str, ValueProto], ...], Tuple[List[int], ...]]: +) -> Tuple[Tuple[Dict[str, ValueProto], ...], Tuple[List[int], ...], int]: """Return the set of unique composite Entities for a Feature View and the indexes at which they appear. This method allows us to query the OnlineStore for data we need only once @@ -758,7 +770,7 @@ def _get_unique_entities_from_values( ] ) ) - return unique_entities, indexes + return unique_entities, indexes, len(rowise) def _drop_unneeded_columns( @@ -835,6 +847,7 @@ def _populate_response_from_feature_data( full_feature_names: bool, requested_features: Iterable[str], table: "FeatureView", + output_len: int, ): """Populate the GetOnlineFeaturesResponse with feature data. @@ -853,33 +866,22 @@ def _populate_response_from_feature_data( requested_features: The names of the features in `feature_data`. This should be ordered in the same way as the data in `feature_data`. table: The FeatureView that `feature_data` was retrieved from. + output_len: The number of result rows in `online_features_response`. """ # Add the feature names to the response. + table_name = table.projection.name_to_use() requested_feature_refs = [ - ( - f"{table.projection.name_to_use()}__{feature_name}" - if full_feature_names - else feature_name - ) + f"{table_name}__{feature_name}" if full_feature_names else feature_name for feature_name in requested_features ] online_features_response.metadata.feature_names.val.extend(requested_feature_refs) - timestamps, statuses, values = zip(*feature_data) - - # Populate the result with data fetched from the OnlineStore - # which is guaranteed to be aligned with `requested_features`. - for ( - feature_idx, - (timestamp_vector, statuses_vector, values_vector), - ) in enumerate(zip(zip(*timestamps), zip(*statuses), zip(*values))): - online_features_response.results.append( - GetOnlineFeaturesResponse.FeatureVector( - values=apply_list_mapping(values_vector, indexes), - statuses=apply_list_mapping(statuses_vector, indexes), - event_timestamps=apply_list_mapping(timestamp_vector, indexes), - ) + # Process each feature vector in a single pass + for timestamp_vector, statuses_vector, values_vector in feature_data: + response_vector = construct_response_feature_vector( + values_vector, statuses_vector, timestamp_vector, indexes, output_len ) + online_features_response.results.append(response_vector) def _populate_response_from_feature_data_v2( @@ -891,6 +893,7 @@ def _populate_response_from_feature_data_v2( indexes: Iterable[List[int]], online_features_response: GetOnlineFeaturesResponse, requested_features: Iterable[str], + output_len: int, ): """Populate the GetOnlineFeaturesResponse with feature data. @@ -908,6 +911,7 @@ def _populate_response_from_feature_data_v2( "customer_fv__daily_transactions"). requested_features: The names of the features in `feature_data`. This should be ordered in the same way as the data in `feature_data`. + output_len: The number of result rows in `online_features_response`. """ # Add the feature names to the response. requested_feature_refs = [(feature_name) for feature_name in requested_features] @@ -917,17 +921,11 @@ def _populate_response_from_feature_data_v2( # Populate the result with data fetched from the OnlineStore # which is guaranteed to be aligned with `requested_features`. - for ( - feature_idx, - (timestamp_vector, statuses_vector, values_vector), - ) in enumerate(zip(zip(*timestamps), zip(*statuses), zip(*values))): - online_features_response.results.append( - GetOnlineFeaturesResponse.FeatureVector( - values=apply_list_mapping(values_vector, indexes), - statuses=apply_list_mapping(statuses_vector, indexes), - event_timestamps=apply_list_mapping(timestamp_vector, indexes), - ) + for timestamp_vector, statuses_vector, values_vector in feature_data: + response_vector = construct_response_feature_vector( + values_vector, statuses_vector, timestamp_vector, indexes, output_len ) + online_features_response.results.append(response_vector) def _convert_entity_key_to_proto_to_dict( @@ -1246,33 +1244,32 @@ def _convert_rows_to_protobuf( requested_features: List[str], read_rows: List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]], ) -> List[Tuple[List[Timestamp], List["FieldStatus.ValueType"], List[ValueProto]]]: - # Each row is a set of features for a given entity key. - # We only need to convert the data to Protobuf once. + # Pre-calculate the length to avoid repeated calculations + n_rows = len(read_rows) + + # Create single instances of commonly used values null_value = ValueProto() - read_row_protos = [] - for read_row in read_rows: - row_ts_proto = Timestamp() - row_ts, feature_data = read_row - # TODO (Ly): reuse whatever timestamp if row_ts is None? - if row_ts is not None: - row_ts_proto.FromDatetime(row_ts) - event_timestamps = [row_ts_proto] * len(requested_features) - if feature_data is None: - statuses = [FieldStatus.NOT_FOUND] * len(requested_features) - values = [null_value] * len(requested_features) - else: - statuses = [] - values = [] - for feature_name in requested_features: - # Make sure order of data is the same as requested_features. - if feature_name not in feature_data: - statuses.append(FieldStatus.NOT_FOUND) - values.append(null_value) - else: - statuses.append(FieldStatus.PRESENT) - values.append(feature_data[feature_name]) - read_row_protos.append((event_timestamps, statuses, values)) - return read_row_protos + null_status = FieldStatus.NOT_FOUND + null_timestamp = Timestamp() + present_status = FieldStatus.PRESENT + + requested_features_vectors = [] + for feature_name in requested_features: + ts_vector = [null_timestamp] * n_rows + status_vector = [null_status] * n_rows + value_vector = [null_value] * n_rows + for idx, read_row in enumerate(read_rows): + row_ts_proto = Timestamp() + row_ts, feature_data = read_row + # TODO (Ly): reuse whatever timestamp if row_ts is None? + if row_ts is not None: + row_ts_proto.FromDatetime(row_ts) + ts_vector[idx] = row_ts_proto + if (feature_data is not None) and (feature_name in feature_data): + status_vector[idx] = present_status + value_vector[idx] = feature_data[feature_name] + requested_features_vectors.append((ts_vector, status_vector, value_vector)) + return requested_features_vectors def has_all_tags( diff --git a/sdk/python/tests/unit/test_unit_feature_store.py b/sdk/python/tests/unit/test_unit_feature_store.py index 8d7b32760a4..3bad0ec6c59 100644 --- a/sdk/python/tests/unit/test_unit_feature_store.py +++ b/sdk/python/tests/unit/test_unit_feature_store.py @@ -38,7 +38,7 @@ def test_get_unique_entities_success(): projection=MockFeatureViewProjection(join_key_map={}), ) - unique_entities, indexes = utils._get_unique_entities( + unique_entities, indexes, output_len = utils._get_unique_entities( table=fv, join_key_values=entity_values, entity_name_to_join_key_map=entity_name_to_join_key_map, @@ -51,6 +51,7 @@ def test_get_unique_entities_success(): assert unique_entities == expected_entities assert indexes == expected_indexes + assert output_len == 3 def test_get_unique_entities_missing_join_key_success(): @@ -74,7 +75,7 @@ def test_get_unique_entities_missing_join_key_success(): projection=MockFeatureViewProjection(join_key_map={}), ) - unique_entities, indexes = utils._get_unique_entities( + unique_entities, indexes, output_len = utils._get_unique_entities( table=fv, join_key_values=entity_values, entity_name_to_join_key_map=entity_name_to_join_key_map, @@ -87,6 +88,7 @@ def test_get_unique_entities_missing_join_key_success(): assert unique_entities == expected_entities assert indexes == expected_indexes + assert output_len == 3 # We're not say anything about the entity_1 missing from the unique_entities list assert "entity_1" not in [entity.keys() for entity in unique_entities] From 08183ed38581eb655e2f6055c50b9223fcf9662e Mon Sep 17 00:00:00 2001 From: Maxim Korolyov Date: Mon, 17 Feb 2025 02:19:27 +0100 Subject: [PATCH 29/30] fix: Add scylladb to online stores list in docs (#5061) add scylladb to online stores deps Signed-off-by: Maxim Korolyov --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e02fb978d7b..1052a93c11e 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,7 @@ The list below contains the functionality that contributors are planning to deve * [x] [Azure Cache for Redis (community plugin)](https://github.com/Azure/feast-azure) * [x] [Postgres (contrib plugin)](https://docs.feast.dev/reference/online-stores/postgres) * [x] [Cassandra / AstraDB (contrib plugin)](https://docs.feast.dev/reference/online-stores/cassandra) + * [x] [ScyllaDB (contrib plugin)](https://docs.feast.dev/reference/online-stores/scylladb) * [x] [Custom online store support](https://docs.feast.dev/how-to-guides/customizing-feast/adding-support-for-a-new-online-store) * **Feature Engineering** * [x] On-demand Transformations (Beta release. See [RFC](https://docs.google.com/document/d/1lgfIw0Drc65LpaxbUu49RCeJgMew547meSJttnUqz7c/edit#)) From 6372f1c3c1c95c8a8e41a22d7d874e1064c9aead Mon Sep 17 00:00:00 2001 From: feast-ci-bot Date: Mon, 17 Feb 2025 22:19:02 +0000 Subject: [PATCH 30/30] chore(release): release 0.46.0 # [0.46.0](https://github.com/feast-dev/feast/compare/v0.45.0...v0.46.0) (2025-02-17) ### Bug Fixes * Add scylladb to online stores list in docs ([#5061](https://github.com/feast-dev/feast/issues/5061)) ([08183ed](https://github.com/feast-dev/feast/commit/08183ed38581eb655e2f6055c50b9223fcf9662e)) * Changed feast operator to set status of featurestore cr to ready based on deployment.status = available ([#5020](https://github.com/feast-dev/feast/issues/5020)) ([fce0d35](https://github.com/feast-dev/feast/commit/fce0d35bc00553269fff6abb7a16897577a2421f)) * Ensure Postgres queries are committed or autocommit is used ([#5039](https://github.com/feast-dev/feast/issues/5039)) ([46f8d7a](https://github.com/feast-dev/feast/commit/46f8d7aa87cfaf36d17c162c4f41cd983a2938d5)) * Fixing the release workflow to refresh the stable branch when the release is not running in the dry run mode. ([#5057](https://github.com/feast-dev/feast/issues/5057)) ([a13fa9b](https://github.com/feast-dev/feast/commit/a13fa9bd18be94b349954e5db66fd30ba4db1d1e)) * Operator - make onlineStore the default service ([#5044](https://github.com/feast-dev/feast/issues/5044)) ([6c92447](https://github.com/feast-dev/feast/commit/6c92447d1507bff02451f77f134df0a24cbd8036)) * Operator - resolve infinite reconciler loop in authz controller ([#5056](https://github.com/feast-dev/feast/issues/5056)) ([11e4548](https://github.com/feast-dev/feast/commit/11e45482b0cace1f3c3a0ddc567a8a1172d6792a)) * Resolve module on windows ([#4827](https://github.com/feast-dev/feast/issues/4827)) ([efbffa4](https://github.com/feast-dev/feast/commit/efbffa4be0f38166ff35f133a9b69bcbd243debd)) * Setting the github_token explicitly to see if that solves the problem. ([#5012](https://github.com/feast-dev/feast/issues/5012)) ([3834ffa](https://github.com/feast-dev/feast/commit/3834ffa31f52b9a68b27a9f898538827ee8e5c39)) * Validate entities when running get_online_features ([#5031](https://github.com/feast-dev/feast/issues/5031)) ([3bb0dca](https://github.com/feast-dev/feast/commit/3bb0dca1692fb7087e967a9fc33a4b08720b13d2)) ### Features * Add SQLite retrieve_online_documents_v2 ([#5032](https://github.com/feast-dev/feast/issues/5032)) ([0fffe21](https://github.com/feast-dev/feast/commit/0fffe211be9db18d318634f47bc9401fd6e218a0)) * Adding Click command to display configuration details ([#5036](https://github.com/feast-dev/feast/issues/5036)) ([ae68e4d](https://github.com/feast-dev/feast/commit/ae68e4de0c184dc2990ea7e8d08d2d7f1613b06f)) * Adding volumes and volumeMounts support to Feature Store CR. ([#4983](https://github.com/feast-dev/feast/issues/4983)) ([ec6f1b7](https://github.com/feast-dev/feast/commit/ec6f1b750ed49ef36c5e3aa9f8db1d030bf80047)) * Moving the job to seperate action so that we can test it easily. ([#5013](https://github.com/feast-dev/feast/issues/5013)) ([b9325b7](https://github.com/feast-dev/feast/commit/b9325b7f42b8866fa43b1c7567e3288dd589020f)) * Operator - make server container creation explicit in the CR ([#5024](https://github.com/feast-dev/feast/issues/5024)) ([b16fb40](https://github.com/feast-dev/feast/commit/b16fb400fd63fdc0168cb1f845638fc003724fd4)) --- CHANGELOG.md | 24 + infra/charts/feast-feature-server/Chart.yaml | 2 +- infra/charts/feast-feature-server/README.md | 4 +- infra/charts/feast-feature-server/values.yaml | 2 +- infra/charts/feast/Chart.yaml | 2 +- infra/charts/feast/README.md | 6 +- .../feast/charts/feature-server/Chart.yaml | 4 +- .../feast/charts/feature-server/README.md | 4 +- .../feast/charts/feature-server/values.yaml | 2 +- .../charts/transformation-service/Chart.yaml | 4 +- .../charts/transformation-service/README.md | 4 +- .../charts/transformation-service/values.yaml | 2 +- infra/charts/feast/requirements.yaml | 4 +- infra/feast-helm-operator/Makefile | 2 +- .../config/manager/kustomization.yaml | 2 +- infra/feast-operator/Makefile | 2 +- .../api/feastversion/version.go | 2 +- .../feast-operator.clusterserviceversion.yaml | 23 +- .../manifests/feast.dev_featurestores.yaml | 6682 ++++++++++++++--- .../config/component_metadata.yaml | 2 +- .../default/related_image_fs_patch.yaml | 2 +- .../config/manager/kustomization.yaml | 2 +- .../config/overlays/odh/params.env | 4 +- infra/feast-operator/dist/install.yaml | 4 +- java/pom.xml | 2 +- sdk/python/feast/ui/package.json | 2 +- sdk/python/feast/ui/yarn.lock | 8 +- ui/package.json | 2 +- 28 files changed, 5622 insertions(+), 1183 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54663a5083e..053edc3df50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +# [0.46.0](https://github.com/feast-dev/feast/compare/v0.45.0...v0.46.0) (2025-02-17) + + +### Bug Fixes + +* Add scylladb to online stores list in docs ([#5061](https://github.com/feast-dev/feast/issues/5061)) ([08183ed](https://github.com/feast-dev/feast/commit/08183ed38581eb655e2f6055c50b9223fcf9662e)) +* Changed feast operator to set status of featurestore cr to ready based on deployment.status = available ([#5020](https://github.com/feast-dev/feast/issues/5020)) ([fce0d35](https://github.com/feast-dev/feast/commit/fce0d35bc00553269fff6abb7a16897577a2421f)) +* Ensure Postgres queries are committed or autocommit is used ([#5039](https://github.com/feast-dev/feast/issues/5039)) ([46f8d7a](https://github.com/feast-dev/feast/commit/46f8d7aa87cfaf36d17c162c4f41cd983a2938d5)) +* Fixing the release workflow to refresh the stable branch when the release is not running in the dry run mode. ([#5057](https://github.com/feast-dev/feast/issues/5057)) ([a13fa9b](https://github.com/feast-dev/feast/commit/a13fa9bd18be94b349954e5db66fd30ba4db1d1e)) +* Operator - make onlineStore the default service ([#5044](https://github.com/feast-dev/feast/issues/5044)) ([6c92447](https://github.com/feast-dev/feast/commit/6c92447d1507bff02451f77f134df0a24cbd8036)) +* Operator - resolve infinite reconciler loop in authz controller ([#5056](https://github.com/feast-dev/feast/issues/5056)) ([11e4548](https://github.com/feast-dev/feast/commit/11e45482b0cace1f3c3a0ddc567a8a1172d6792a)) +* Resolve module on windows ([#4827](https://github.com/feast-dev/feast/issues/4827)) ([efbffa4](https://github.com/feast-dev/feast/commit/efbffa4be0f38166ff35f133a9b69bcbd243debd)) +* Setting the github_token explicitly to see if that solves the problem. ([#5012](https://github.com/feast-dev/feast/issues/5012)) ([3834ffa](https://github.com/feast-dev/feast/commit/3834ffa31f52b9a68b27a9f898538827ee8e5c39)) +* Validate entities when running get_online_features ([#5031](https://github.com/feast-dev/feast/issues/5031)) ([3bb0dca](https://github.com/feast-dev/feast/commit/3bb0dca1692fb7087e967a9fc33a4b08720b13d2)) + + +### Features + +* Add SQLite retrieve_online_documents_v2 ([#5032](https://github.com/feast-dev/feast/issues/5032)) ([0fffe21](https://github.com/feast-dev/feast/commit/0fffe211be9db18d318634f47bc9401fd6e218a0)) +* Adding Click command to display configuration details ([#5036](https://github.com/feast-dev/feast/issues/5036)) ([ae68e4d](https://github.com/feast-dev/feast/commit/ae68e4de0c184dc2990ea7e8d08d2d7f1613b06f)) +* Adding volumes and volumeMounts support to Feature Store CR. ([#4983](https://github.com/feast-dev/feast/issues/4983)) ([ec6f1b7](https://github.com/feast-dev/feast/commit/ec6f1b750ed49ef36c5e3aa9f8db1d030bf80047)) +* Moving the job to seperate action so that we can test it easily. ([#5013](https://github.com/feast-dev/feast/issues/5013)) ([b9325b7](https://github.com/feast-dev/feast/commit/b9325b7f42b8866fa43b1c7567e3288dd589020f)) +* Operator - make server container creation explicit in the CR ([#5024](https://github.com/feast-dev/feast/issues/5024)) ([b16fb40](https://github.com/feast-dev/feast/commit/b16fb400fd63fdc0168cb1f845638fc003724fd4)) + # [0.45.0](https://github.com/feast-dev/feast/compare/v0.44.0...v0.45.0) (2025-02-04) diff --git a/infra/charts/feast-feature-server/Chart.yaml b/infra/charts/feast-feature-server/Chart.yaml index cfcf4d75c1c..d8ed41d2782 100644 --- a/infra/charts/feast-feature-server/Chart.yaml +++ b/infra/charts/feast-feature-server/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: feast-feature-server description: Feast Feature Server in Go or Python type: application -version: 0.45.0 +version: 0.46.0 keywords: - machine learning - big data diff --git a/infra/charts/feast-feature-server/README.md b/infra/charts/feast-feature-server/README.md index 91a0af4e27c..dc907ab8acf 100644 --- a/infra/charts/feast-feature-server/README.md +++ b/infra/charts/feast-feature-server/README.md @@ -1,6 +1,6 @@ # Feast Python / Go Feature Server Helm Charts -Current chart version is `0.45.0` +Current chart version is `0.46.0` ## Installation @@ -40,7 +40,7 @@ See [here](https://github.com/feast-dev/feast/tree/master/examples/python-helm-d | fullnameOverride | string | `""` | | | image.pullPolicy | string | `"IfNotPresent"` | | | image.repository | string | `"feastdev/feature-server"` | Docker image for Feature Server repository | -| image.tag | string | `"0.45.0"` | The Docker image tag (can be overwritten if custom feature server deps are needed for on demand transforms) | +| image.tag | string | `"0.46.0"` | The Docker image tag (can be overwritten if custom feature server deps are needed for on demand transforms) | | imagePullSecrets | list | `[]` | | | livenessProbe.initialDelaySeconds | int | `30` | | | livenessProbe.periodSeconds | int | `30` | | diff --git a/infra/charts/feast-feature-server/values.yaml b/infra/charts/feast-feature-server/values.yaml index 3655dd1154e..db2fbfb28bb 100644 --- a/infra/charts/feast-feature-server/values.yaml +++ b/infra/charts/feast-feature-server/values.yaml @@ -9,7 +9,7 @@ image: repository: feastdev/feature-server pullPolicy: IfNotPresent # image.tag -- The Docker image tag (can be overwritten if custom feature server deps are needed for on demand transforms) - tag: 0.45.0 + tag: 0.46.0 logLevel: "WARNING" # Set log level DEBUG, INFO, WARNING, ERROR, and CRITICAL (case-insensitive) diff --git a/infra/charts/feast/Chart.yaml b/infra/charts/feast/Chart.yaml index 236a2e2896d..d0dfebbf2b5 100644 --- a/infra/charts/feast/Chart.yaml +++ b/infra/charts/feast/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v1 description: Feature store for machine learning name: feast -version: 0.45.0 +version: 0.46.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/README.md b/infra/charts/feast/README.md index 28604c7199f..e89c8331d30 100644 --- a/infra/charts/feast/README.md +++ b/infra/charts/feast/README.md @@ -8,7 +8,7 @@ This repo contains Helm charts for Feast Java components that are being installe ## Chart: Feast -Feature store for machine learning Current chart version is `0.45.0` +Feature store for machine learning Current chart version is `0.46.0` ## Installation @@ -65,8 +65,8 @@ See [here](https://github.com/feast-dev/feast/tree/master/examples/java-demo) fo | Repository | Name | Version | |------------|------|---------| | https://charts.helm.sh/stable | redis | 10.5.6 | -| https://feast-helm-charts.storage.googleapis.com | feature-server(feature-server) | 0.45.0 | -| https://feast-helm-charts.storage.googleapis.com | transformation-service(transformation-service) | 0.45.0 | +| https://feast-helm-charts.storage.googleapis.com | feature-server(feature-server) | 0.46.0 | +| https://feast-helm-charts.storage.googleapis.com | transformation-service(transformation-service) | 0.46.0 | ## Values diff --git a/infra/charts/feast/charts/feature-server/Chart.yaml b/infra/charts/feast/charts/feature-server/Chart.yaml index b9cc4a6a5a1..a4c10bdd5b4 100644 --- a/infra/charts/feast/charts/feature-server/Chart.yaml +++ b/infra/charts/feast/charts/feature-server/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 description: "Feast Feature Server: Online feature serving service for Feast" name: feature-server -version: 0.45.0 -appVersion: v0.45.0 +version: 0.46.0 +appVersion: v0.46.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/charts/feature-server/README.md b/infra/charts/feast/charts/feature-server/README.md index 236224ed616..697596b2eb2 100644 --- a/infra/charts/feast/charts/feature-server/README.md +++ b/infra/charts/feast/charts/feature-server/README.md @@ -1,6 +1,6 @@ # feature-server -![Version: 0.45.0](https://img.shields.io/badge/Version-0.45.0-informational?style=flat-square) ![AppVersion: v0.45.0](https://img.shields.io/badge/AppVersion-v0.45.0-informational?style=flat-square) +![Version: 0.46.0](https://img.shields.io/badge/Version-0.46.0-informational?style=flat-square) ![AppVersion: v0.46.0](https://img.shields.io/badge/AppVersion-v0.46.0-informational?style=flat-square) Feast Feature Server: Online feature serving service for Feast @@ -17,7 +17,7 @@ Feast Feature Server: Online feature serving service for Feast | envOverrides | object | `{}` | Extra environment variables to set | | image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | | image.repository | string | `"feastdev/feature-server-java"` | Docker image for Feature Server repository | -| image.tag | string | `"0.45.0"` | Image tag | +| image.tag | string | `"0.46.0"` | Image tag | | ingress.grpc.annotations | object | `{}` | Extra annotations for the ingress | | ingress.grpc.auth.enabled | bool | `false` | Flag to enable auth | | ingress.grpc.class | string | `"nginx"` | Which ingress controller to use | diff --git a/infra/charts/feast/charts/feature-server/values.yaml b/infra/charts/feast/charts/feature-server/values.yaml index 50629b99b22..48681f83ca0 100644 --- a/infra/charts/feast/charts/feature-server/values.yaml +++ b/infra/charts/feast/charts/feature-server/values.yaml @@ -5,7 +5,7 @@ image: # image.repository -- Docker image for Feature Server repository repository: feastdev/feature-server-java # image.tag -- Image tag - tag: 0.45.0 + tag: 0.46.0 # image.pullPolicy -- Image pull policy pullPolicy: IfNotPresent diff --git a/infra/charts/feast/charts/transformation-service/Chart.yaml b/infra/charts/feast/charts/transformation-service/Chart.yaml index ea776c2224f..12123e505e3 100644 --- a/infra/charts/feast/charts/transformation-service/Chart.yaml +++ b/infra/charts/feast/charts/transformation-service/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 description: "Transformation service: to compute on-demand features" name: transformation-service -version: 0.45.0 -appVersion: v0.45.0 +version: 0.46.0 +appVersion: v0.46.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/charts/transformation-service/README.md b/infra/charts/feast/charts/transformation-service/README.md index 0c6ccaa66e8..4dfd213bf2e 100644 --- a/infra/charts/feast/charts/transformation-service/README.md +++ b/infra/charts/feast/charts/transformation-service/README.md @@ -1,6 +1,6 @@ # transformation-service -![Version: 0.45.0](https://img.shields.io/badge/Version-0.45.0-informational?style=flat-square) ![AppVersion: v0.45.0](https://img.shields.io/badge/AppVersion-v0.45.0-informational?style=flat-square) +![Version: 0.46.0](https://img.shields.io/badge/Version-0.46.0-informational?style=flat-square) ![AppVersion: v0.46.0](https://img.shields.io/badge/AppVersion-v0.46.0-informational?style=flat-square) Transformation service: to compute on-demand features @@ -13,7 +13,7 @@ Transformation service: to compute on-demand features | envOverrides | object | `{}` | Extra environment variables to set | | image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | | image.repository | string | `"feastdev/feature-transformation-server"` | Docker image for Transformation Server repository | -| image.tag | string | `"0.45.0"` | Image tag | +| image.tag | string | `"0.46.0"` | Image tag | | nodeSelector | object | `{}` | Node labels for pod assignment | | podLabels | object | `{}` | Labels to be added to Feast Serving pods | | replicaCount | int | `1` | Number of pods that will be created | diff --git a/infra/charts/feast/charts/transformation-service/values.yaml b/infra/charts/feast/charts/transformation-service/values.yaml index 737f1e76937..3d056d5b25f 100644 --- a/infra/charts/feast/charts/transformation-service/values.yaml +++ b/infra/charts/feast/charts/transformation-service/values.yaml @@ -5,7 +5,7 @@ image: # image.repository -- Docker image for Transformation Server repository repository: feastdev/feature-transformation-server # image.tag -- Image tag - tag: 0.45.0 + tag: 0.46.0 # image.pullPolicy -- Image pull policy pullPolicy: IfNotPresent diff --git a/infra/charts/feast/requirements.yaml b/infra/charts/feast/requirements.yaml index 745d3ccb8dc..11d9026f2df 100644 --- a/infra/charts/feast/requirements.yaml +++ b/infra/charts/feast/requirements.yaml @@ -1,12 +1,12 @@ dependencies: - name: feature-server alias: feature-server - version: 0.45.0 + version: 0.46.0 condition: feature-server.enabled repository: https://feast-helm-charts.storage.googleapis.com - name: transformation-service alias: transformation-service - version: 0.45.0 + version: 0.46.0 condition: transformation-service.enabled repository: https://feast-helm-charts.storage.googleapis.com - name: redis diff --git a/infra/feast-helm-operator/Makefile b/infra/feast-helm-operator/Makefile index 5031993c709..76614ae37af 100644 --- a/infra/feast-helm-operator/Makefile +++ b/infra/feast-helm-operator/Makefile @@ -3,7 +3,7 @@ # To re-generate a bundle for another specific version without changing the standard setup, you can: # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) -VERSION ?= 0.45.0 +VERSION ?= 0.46.0 # CHANNELS define the bundle channels used in the bundle. # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") diff --git a/infra/feast-helm-operator/config/manager/kustomization.yaml b/infra/feast-helm-operator/config/manager/kustomization.yaml index e8ed0e83464..bc970e7b408 100644 --- a/infra/feast-helm-operator/config/manager/kustomization.yaml +++ b/infra/feast-helm-operator/config/manager/kustomization.yaml @@ -5,4 +5,4 @@ kind: Kustomization images: - name: controller newName: feastdev/feast-helm-operator - newTag: 0.45.0 + newTag: 0.46.0 diff --git a/infra/feast-operator/Makefile b/infra/feast-operator/Makefile index e272e963837..9c90f02d415 100644 --- a/infra/feast-operator/Makefile +++ b/infra/feast-operator/Makefile @@ -3,7 +3,7 @@ # To re-generate a bundle for another specific version without changing the standard setup, you can: # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) -VERSION ?= 0.45.0 +VERSION ?= 0.46.0 # CHANNELS define the bundle channels used in the bundle. # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") diff --git a/infra/feast-operator/api/feastversion/version.go b/infra/feast-operator/api/feastversion/version.go index 9c0f52c260c..43c518ebbff 100644 --- a/infra/feast-operator/api/feastversion/version.go +++ b/infra/feast-operator/api/feastversion/version.go @@ -17,4 +17,4 @@ limitations under the License. package feastversion // Feast release version -const FeastVersion = "0.45.0" +const FeastVersion = "0.46.0" diff --git a/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml b/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml index ce1e45aa99a..734508cfecb 100644 --- a/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml +++ b/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml @@ -18,15 +18,18 @@ metadata: "apiVersion": "feast.dev/v1alpha1", "kind": "FeatureStore", "metadata": { - "name": "sample-all-services" + "name": "sample-all-servers" }, "spec": { "feastProject": "my_project", "services": { - "offlineStore": {}, - "onlineStore": {}, + "offlineStore": { + "server": {} + }, "registry": { - "local": {} + "local": { + "server": {} + } }, "ui": {} } @@ -34,10 +37,10 @@ metadata: } ] capabilities: Basic Install - createdAt: "2025-02-04T20:12:01Z" + createdAt: "2025-02-17T22:19:00Z" operators.operatorframework.io/builder: operator-sdk-v1.38.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 - name: feast-operator.v0.45.0 + name: feast-operator.v0.46.0 namespace: placeholder spec: apiservicedefinitions: {} @@ -179,8 +182,8 @@ spec: - /manager env: - name: RELATED_IMAGE_FEATURE_SERVER - value: docker.io/feastdev/feature-server:0.45.0 - image: feastdev/feast-operator:0.45.0 + value: docker.io/feastdev/feature-server:0.46.0 + image: feastdev/feast-operator:0.46.0 livenessProbe: httpGet: path: /healthz @@ -270,6 +273,6 @@ spec: name: Feast Community url: https://lf-aidata.atlassian.net/wiki/spaces/FEAST/ relatedImages: - - image: docker.io/feastdev/feature-server:0.45.0 + - image: docker.io/feastdev/feature-server:0.46.0 name: feature-server - version: 0.45.0 + version: 0.46.0 diff --git a/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml b/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml index 9c225243c64..8806a5b1f3a 100644 --- a/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml +++ b/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml @@ -26,30 +26,53 @@ spec: name: v1alpha1 schema: openAPIV3Schema: + description: FeatureStore is the Schema for the featurestores API properties: apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. type: string kind: + description: Kind is a string value representing the REST resource this + object represents. type: string metadata: type: object spec: + description: FeatureStoreSpec defines the desired state of FeatureStore properties: authz: + description: AuthzConfig defines the authorization settings for the + deployed Feast services. properties: kubernetes: + description: |- + KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. + https://kubernetes. properties: roles: + description: The Kubernetes RBAC roles to be deployed in the + same namespace of the FeatureStore. items: type: string type: array type: object oidc: + description: |- + OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. + https://auth0. properties: secretRef: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -61,148 +84,73 @@ spec: - message: One selection required between kubernetes or oidc. rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, c)' feastProject: + description: FeastProject is the Feast project id. pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ type: string services: + description: FeatureStoreServices defines the desired feast services. + An ephemeral onlineStore feature server is deployed by default. properties: deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. properties: rollingUpdate: + description: |- + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. properties: maxSurge: anyOf: - type: integer - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. x-kubernetes-int-or-string: true maxUnavailable: anyOf: - type: integer - type: string + description: The maximum number of pods that can be unavailable + during the update. x-kubernetes-int-or-string: true type: object type: + description: Type of deployment. Can be "Recreate" or "RollingUpdate". + Default is RollingUpdate. type: string type: object disableInitContainers: + description: Disable the 'feast repo initialization' initContainer type: boolean offlineStore: + description: OfflineStore configures the offline store service 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: + description: OfflineStorePersistence configures the persistence + settings for the offline store service properties: file: + description: OfflineStoreFilePersistence configures the + file-based persistence for the offline store service properties: pvc: + description: PvcConfig defines the settings for a + persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent volume + access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -211,6 +159,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -219,20 +170,33 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which this + persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -255,17 +219,30 @@ spec: type: string type: object store: + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the secret + key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you want + to use. enum: - snowflake.offline - bigquery @@ -273,7 +250,6 @@ spec: - spark - postgres - trino - - redis - athena - mssql type: string @@ -285,181 +261,338 @@ 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: + description: Creates a remote offline server container properties: - claims: + env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + 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: + description: EnvFromSource represents the source of + a set of ConfigMaps properties: - configMapKeyRef: + configMapRef: + description: The ConfigMap to select from properties: - key: - type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined 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: + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from 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: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - required: - - resource + optional: + description: Specify whether the Secret must + be defined + type: boolean type: object x-kubernetes-map-type: atomic - secretKeyRef: + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: - key: - type: string name: - default: "" + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string - optional: - type: boolean required: - - key + - name type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for a feast + service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + 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' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of a Volume + within a container. properties: - name: - default: "" + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: name: - default: "" + description: This must match the Name of a Volume. type: string - optional: + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + type: string + required: + - mountPath + - name 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 + type: object + type: object + onlineStore: + description: OnlineStore configures the online store service + properties: persistence: + description: OnlineStorePersistence configures the persistence + settings for the online store service properties: file: + description: OnlineStoreFilePersistence configures the + file-based persistence for the online store service properties: path: type: string pvc: + description: PvcConfig defines the settings for a + persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent volume + access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -468,6 +601,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -476,20 +612,33 @@ spec: - 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 + description: Requests describes the minimum + amount of compute resources required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which this + persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -517,17 +666,30 @@ spec: rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) : true' store: + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the secret + key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you want + to use. enum: - snowflake.online - redis @@ -554,121 +716,109 @@ spec: 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 - 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: + description: Creates a feature server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -681,24 +831,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of + a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must + be defined type: boolean type: object x-kubernetes-map-type: atomic @@ -707,8 +875,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -716,21 +889,169 @@ spec: - error - critical type: string + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for a feast + service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + 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' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + type: object + type: object + registry: + description: Registry configures the registry service. One selection + is required. Local is the default setting. + properties: + local: + description: LocalRegistryConfig configures the registry service + properties: persistence: + description: RegistryPersistence configures the persistence + settings for the registry service properties: file: + description: RegistryFilePersistence configures the + file-based persistence for the registry service properties: path: type: string pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. properties: create: + description: Settings for creating a new PVC properties: accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. items: type: string type: array resources: + description: Resources describes the storage + resource requirements for a volume. properties: limits: additionalProperties: @@ -739,6 +1060,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -747,20 +1071,34 @@ spec: - 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 + description: Requests describes the + minimum amount of compute resources + required. type: object type: object storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. type: string type: object x-kubernetes-validations: - message: PvcCreate is immutable rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string ref: + description: Reference to an existing field properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -800,17 +1138,30 @@ spec: rule: '(has(self.s3_additional_kwargs) && has(self.path)) ? self.path.startsWith(''s3://'') : true' store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service properties: secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName type: string secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic type: + description: Type of the persistence type you + want to use. enum: - sql - snowflake.registry @@ -824,82 +1175,352 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' - resources: + server: + description: Creates a registry server container properties: - claims: + env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string - required: - - name - type: object + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + 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: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + description: ResourceRequirements describes the compute + resource requirements. properties: - tlsCrt: - type: string - tlsKey: - type: string + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the minimum amount + of compute resources required. + type: object type: object - secretRef: + tls: + description: TlsConfigs configures server TLS for + a feast service. properties: - name: - default: "" - type: string + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + 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' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of + a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. + type: string + required: + - mountPath + - name + type: object + type: array 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: + description: RemoteRegistryConfig points to a remote feast + registry server. properties: feastRef: + description: Reference to an existing `FeatureStore` CR + in the same k8s cluster. properties: name: + description: Name of the FeatureStore type: string namespace: + description: Namespace of the FeatureStore type: string required: - name type: object hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` type: string tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. properties: certName: + description: defines the configmap key name for the + client TLS cert. type: string configMapRef: + description: references the local k8s configmap where + the TLS cert resides properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -917,63 +1538,107 @@ spec: - message: One selection required. rule: '[has(self.local), has(self.remote)].exists_one(c, c)' ui: + description: Creates a UI server container properties: env: items: + description: EnvVar represents an environment variable present + in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap or + its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for volumes, + optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the pod's + namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret or its + key must be defined type: boolean required: - key @@ -986,24 +1651,42 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of a set + of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to each + key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must be + defined type: boolean type: object x-kubernetes-map-type: atomic @@ -1012,8 +1695,13 @@ spec: image: type: string imagePullPolicy: + description: PullPolicy describes a policy for if/when to + pull a container image type: string logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". enum: - debug - info @@ -1022,11 +1710,20 @@ spec: - critical type: string resources: + description: ResourceRequirements describes the compute resource + requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -1042,6 +1739,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1050,23 +1750,40 @@ spec: - 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 + description: Requests describes the minimum amount of + compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. useful + in an openshift cluster, for example, where TLS is configured + by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key names + for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where the + TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -1075,380 +1792,3109 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + description: VolumeMounts defines the list of volumes that + should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array type: object - type: object - required: - - feastProject - type: object - status: - properties: - applied: - properties: - authz: - properties: - kubernetes: - properties: - roles: - items: + volumes: + description: Volumes specifies the volumes to mount in the FeatureStore + deployment. + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: |- + awsElasticBlockStore represents an AWS Disk resource that is attached to a + kubelet's host machine and then exposed to th + properties: + fsType: + description: fsType is the filesystem type of the volume + that you want to mount. type: string - type: array - type: object - oidc: - properties: - secretRef: - properties: - name: - default: "" + partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. + format: int32 + type: integer + readOnly: + description: |- + readOnly value true will force the readOnly setting in VolumeMounts. + More info: https://kubernetes. + type: boolean + volumeID: + description: |- + volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). + More info: https://kubernetes. + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in + the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the + blob storage + type: string + fsType: + description: |- + fsType is Filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage accoun' + type: string + readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime + properties: + monitors: + description: |- + monitors is Required: Monitors is a collection of Ceph monitors + More info: https://examples.k8s. + items: type: string - type: object - x-kubernetes-map-type: atomic - required: - - secretRef - type: object - type: object - x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, - c)' - feastProject: - pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ - type: string - services: - properties: - deploymentStrategy: - properties: - rollingUpdate: - properties: - maxSurge: - anyOf: - - 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: + type: array + x-kubernetes-list-type: atomic + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default is /' + type: string + readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is + the path to key ring for User, default is /etc/ceph/user.' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is + empty.' properties: name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - value: + type: object + x-kubernetes-map-type: atomic + user: + description: |- + user is optional: User is the rados user name, default is admin + More info: https://examples.k8s. + type: string + required: + - monitors + type: object + cinder: + description: |- + cinder represents a cinder volume attached and mounted on kubelets host machine. + More info: https://examples.k8s. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + type: string + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef is optional: points to a secret object containing parameters used to connect + to OpenStack. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - valueFrom: + type: object + x-kubernetes-map-type: atomic + volumeID: + description: |- + volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default.' + format: int32 + type: integer + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta fea + properties: + driver: + description: driver is the name of the CSI driver that + handles this volume. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + type: string + nodePublishSecretRef: + description: |- + nodePublishSecretRef is a reference to the secret object containing + sensitive information to pass to the CSI driver to c + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: |- + readOnly specifies a read-only configuration for the volume. + Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: |- + volumeAttributes stores driver-specific properties that are passed to the CSI + driver. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name, namespace + and uid are supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path.' + type: string + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + description: |- + emptyDir represents a temporary directory that shares a pod's lifetime. + More info: https://kubernetes. + properties: + medium: + description: medium represents what type of storage + medium should back this directory. + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: sizeLimit is the total amount of local + storage required for this EmptyDir volume. + 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 + ephemeral: + description: ephemeral represents a volume that is handled + by a cluster storage driver. + properties: + volumeClaimTemplate: + description: Will be used to create a stand-alone PVC + to provision the volume. + properties: + metadata: + description: |- + May contain labels and annotations that will be copied into the PVC + when creating it. + type: object + spec: + description: The specification for the PersistentVolumeClaim. properties: - configMapKeyRef: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s. properties: - key: + apiGroup: + description: APIGroup is the group for the + resource being referenced. + type: string + kind: + description: Kind is the type of resource + being referenced type: string name: - default: "" + description: Name is the name of resource + being referenced type: string - optional: - type: boolean required: - - key + - kind + - name type: object x-kubernetes-map-type: atomic - fieldRef: + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. properties: - apiVersion: + apiGroup: + description: APIGroup is the group for the + resource being referenced. type: string - fieldPath: + kind: + description: Kind is the type of resource + being referenced type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: + name: + description: Name is the name of resource + being referenced 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: + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking. type: string required: - - resource + - kind + - name type: object - x-kubernetes-map-type: atomic - secretKeyRef: + resources: + description: resources represents the minimum + resources the volume should have. properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the minimum + amount of compute resources required. + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes. + type: string + volumeAttributesClassName: + description: volumeAttributesClassName may be + used to set the VolumeAttributesClass used + by this claim. + type: string + volumeMode: + description: volumeMode defines what type of + volume is required by the claim. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string type: object required: - - name + - spec type: object - type: array - envFrom: - items: + type: object + fc: + description: fc represents a Fibre Channel resource that + is attached to a kubelet's host machine and then exposed + to the pod. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + description: "wwids Optional: FC volume world wide identifiers + (wwids)\nEither wwids or combination of targetWWNs + and lun must be set, " + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + description: |- + flexVolume represents a generic volume resource that is + provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use + for this volume. + type: string + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: |- + readOnly is Optional: defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef is Optional: secretRef is reference to the secret object containing + sensitive information to pass to the plugi properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. 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: - properties: - pvc: - properties: - create: - properties: - accessModes: - items: - type: string - type: array - resources: - properties: - 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 - storageClassName: - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. + properties: + datasetName: + description: |- + datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker + should be considered as depreca + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: |- + gcePersistentDisk represents a GCE Disk resource that is attached to a + kubelet's host machine and then exposed to the po + properties: + fsType: + description: fsType is filesystem type of the volume + that you want to mount. + type: string + partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. + format: int32 + type: integer + pdName: + description: |- + pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. + More info: https://kubernetes. + type: string + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://kubernetes. + type: boolean + required: + - pdName + type: object + gitRepo: + description: |- + gitRepo represents a git repository at a particular revision. + DEPRECATED: GitRepo is deprecated. + properties: + directory: + description: |- + directory is the target directory name. + Must not contain or start with '..'. If '. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: |- + glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. + properties: + endpoints: + description: |- + endpoints is the endpoint name that details Glusterfs topology. + More info: https://examples.k8s. + type: string + path: + description: |- + path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod + type: string + readOnly: + description: |- + readOnly here will force the Glusterfs volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: |- + hostPath represents a pre-existing file or directory on the host + machine that is directly exposed to the container. + properties: + path: + description: |- + path of the directory on the host. + If the path is a symlink, it will follow the link to the real path. + type: string + type: + description: |- + type for HostPath Volume + Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + type: string + required: + - path + type: object + iscsi: + description: |- + iscsi represents an ISCSI Disk resource that is attached to a + kubelet's host machine and then exposed to the pod. + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: fsType is the filesystem type of the volume + that you want to mount. + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: |- + iscsiInterface is the interface Name that uses an iSCSI transport. + Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: |- + name of the volume. + Must be a DNS_LABEL and unique within the pod. + More info: https://kubernetes. + type: string + nfs: + description: |- + nfs represents an NFS mount on the host that shares a pod's lifetime + More info: https://kubernetes. + properties: + path: + description: |- + path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs + type: string + readOnly: + description: |- + readOnly here will force the NFS export to be mounted with read-only permissions. + Defaults to false. + type: boolean + server: + description: |- + server is the hostname or IP address of the NFS server. + More info: https://kubernetes. + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: |- + persistentVolumeClaimVolumeSource represents a reference to a + PersistentVolumeClaim in the same namespace. + properties: + claimName: + description: claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + type: string + readOnly: + description: |- + readOnly Will force the ReadOnly setting in VolumeMounts. + Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: |- + fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating system. + Ex. + type: string + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along + with other supported volume types + properties: + clusterTrustBundle: + description: ClusterTrustBundle allows a pod to + access the `.spec. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. + type: string + required: + - path + type: object + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: optional specify whether the + ConfigMap or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the + downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name, namespace and uid are supported.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file to + be created. Must not be absolute or + contain the ''..'' path.' + type: string + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + description: secret information about the secret + data to project + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. + type: string + expirationSeconds: + description: |- + expirationSeconds is the requested duration of validity of the service + account token. + format: int64 + type: integer + path: + description: |- + path is the path relative to the mount point of the file to project the + token into. + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: |- + group to map volume access to + Default is no group + type: string + readOnly: + description: |- + readOnly here will force the Quobyte volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: |- + registry represents a single or multiple Quobyte Registry services + specified as a string as host:port pair (multiple ent + type: string + tenant: + description: |- + tenant owning the given Quobyte volume in the Backend + Used with dynamically provisioned Quobyte volumes, value is set by + type: string + user: + description: |- + user to map volume access to + Defaults to serivceaccount user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: |- + rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. + properties: + fsType: + description: fsType is the filesystem type of the volume + that you want to mount. + type: string + image: + description: |- + image is the rados image name. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + keyring: + description: |- + keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. + More info: https://examples.k8s. + type: string + monitors: + description: |- + monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + description: |- + pool is the rados pool name. + Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://examples.k8s. + type: boolean + secretRef: + description: |- + secretRef is name of the authentication secret for RBDUser. If provided + overrides keyring. + Default is nil. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: |- + user is the rados user name. + Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef references to the secret for ScaleIO user and other + sensitive information. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool + associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: |- + volumeName is the name of a volume already created in the ScaleIO system + that is associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: |- + secret represents a secret that should populate this volume. + More info: https://kubernetes. + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default.' + format: int32 + type: integer + items: + description: |- + items If unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: |- + secretName is the name of the secret in the pod's namespace to use. + More info: https://kubernetes. + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef specifies the secret to use for obtaining the StorageOS API + credentials. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: |- + volumeName is the human-readable name of the StorageOS volume. Volume + names are only unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of + the volume within StorageOS. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: |- + fsType is filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + required: + - feastProject + type: object + status: + description: FeatureStoreStatus defines the observed state of FeatureStore + properties: + applied: + description: Shows the currently applied feast configuration, including + any pertinent defaults + properties: + authz: + description: AuthzConfig defines the authorization settings for + the deployed Feast services. + properties: + kubernetes: + description: |- + KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. + https://kubernetes. + properties: + roles: + description: The Kubernetes RBAC roles to be deployed + in the same namespace of the FeatureStore. + items: + type: string + type: array + type: object + oidc: + description: |- + OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. + https://auth0. + properties: + secretRef: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object + type: object + x-kubernetes-validations: + - message: One selection required between kubernetes or oidc. + rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + c)' + feastProject: + description: FeastProject is the Feast project id. + pattern: ^[A-Za-z0-9][A-Za-z0-9_]*$ + type: string + services: + description: FeatureStoreServices defines the desired feast services. + An ephemeral onlineStore feature server is deployed by default. + properties: + deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. + properties: + rollingUpdate: + description: |- + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: The maximum number of pods that can be + unavailable during the update. + x-kubernetes-int-or-string: true + type: object + type: + description: Type of deployment. Can be "Recreate" or + "RollingUpdate". Default is RollingUpdate. + type: string + type: object + disableInitContainers: + description: Disable the 'feast repo initialization' initContainer + type: boolean + offlineStore: + description: OfflineStore configures the offline store service + properties: + persistence: + description: OfflineStorePersistence configures the persistence + settings for the offline store service + properties: + file: + description: OfflineStoreFilePersistence configures + the file-based persistence for the offline store + service + properties: + pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. + properties: + create: + description: Settings for creating a new PVC + properties: + accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the storage + resource requirements for a volume. + properties: + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the + minimum amount of compute resources + required. + type: object + type: object + storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. + type: string + ref: + description: Reference to an existing field + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + 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('^/[^:]*$') + type: + enum: + - file + - dask + - duckdb + type: string + type: object + store: + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service + properties: + secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type you + want to use. + enum: + - snowflake.offline + - bigquery + - redshift + - spark + - postgres + - trino + - athena + - mssql + 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: + description: Creates a remote offline server container + properties: + env: + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for + a feast service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + 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' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of + a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. + type: string + required: + - mountPath + - name + type: object + type: array + type: object + type: object + onlineStore: + description: OnlineStore configures the online store service + properties: + persistence: + description: OnlineStorePersistence configures the persistence + settings for the online store service + properties: + file: + description: OnlineStoreFilePersistence configures + the file-based persistence for the online store + service + properties: + path: + type: string + pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. + properties: + create: + description: Settings for creating a new PVC + properties: + accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the storage + resource requirements for a volume. + properties: + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the + minimum amount of compute resources + required. + type: object + type: object + storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. + type: string + ref: + description: Reference to an existing field + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + 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('^/[^:]*$') + type: object + x-kubernetes-validations: + - message: Ephemeral stores must have absolute paths. + rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') + : 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: Online store does not support S3 or GS + buckets. + rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + store: + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service + properties: + secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type you + want to use. + 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)' + server: + description: Creates a feature server container + properties: + env: + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for + a feast service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" type: string - ref: + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + 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' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of + a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. + type: string + required: + - mountPath + - name + type: object + type: array + type: object + type: object + registry: + description: Registry configures the registry service. One + selection is required. Local is the default setting. + properties: + local: + description: LocalRegistryConfig configures the registry + service + properties: + persistence: + description: RegistryPersistence configures the persistence + settings for the registry service + properties: + file: + description: RegistryFilePersistence configures + the file-based persistence for the registry + service + properties: + path: + type: string + pvc: + description: PvcConfig defines the settings + for a persistent file store based on PVCs. + properties: + create: + description: Settings for creating a new + PVC + properties: + accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to + ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the + storage resource requirements for + a volume. + properties: + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes + the minimum amount of compute + resources required. + type: object + type: object + storageClassName: + description: StorageClassName is the + name of an existing StorageClass + to which this persistent volume + belongs. + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. + type: string + ref: + description: Reference to an existing + field + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + 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: + 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: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service + properties: + secretKeyName: + description: By default, the selected store + "type" is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should + be placed as-is from the "feature_store.yaml" + under the secret key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type + you want to use. + 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: + description: Creates a registry server container + properties: + env: + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any + type: string + valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the + pod: supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be + a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for + if/when to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + resources: + description: ResourceRequirements describes the + compute resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the minimum + amount of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS + for a feast service. + properties: + disable: + description: will disable TLS for the feast + service. useful in an openshift cluster, + for example, where TLS is configured by + default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret + where the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic - 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('^/[^:]*$') - type: - enum: - - file - - dask - - duckdb + - message: '`secretRef` required if `disable` + is false.' + rule: '(!has(self.disable) || !self.disable) + ? has(self.secretRef) : true' + volumeMounts: + description: VolumeMounts defines the list of + volumes that should be mounted into the feast + container. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of + a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should + be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + type: object + type: object + remote: + description: RemoteRegistryConfig points to a remote feast + registry server. + properties: + feastRef: + description: Reference to an existing `FeatureStore` + CR in the same k8s cluster. + properties: + name: + description: Name of the FeatureStore + type: string + namespace: + description: Namespace of the FeatureStore type: string + required: + - name type: object - store: + hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` + type: string + tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. properties: - secretKeyName: + certName: + description: defines the configmap key name for + the client TLS cert. type: string - secretRef: + configMapRef: + description: references the local k8s configmap + where the TLS cert resides properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic - type: - enum: - - snowflake.offline - - bigquery - - redshift - - spark - - postgres - - trino - - redis - - athena - - mssql - type: string required: - - secretRef - - type + - certName + - configMapRef 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, + - message: One selection required. + rule: '[has(self.hostname), has(self.feastRef)].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 - onlineStore: + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.local), has(self.remote)].exists_one(c, + c)' + ui: + description: Creates a UI server container properties: env: items: + description: EnvVar represents an environment variable + present in a Container. properties: name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: configMapKeyRef: + description: Selects a key of a ConfigMap. properties: key: + description: The key to select. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap + or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' properties: apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string fieldPath: + description: Path of the field to select + in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. properties: containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: + description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: key: + description: The key of the secret to select + from. Must be a valid secret key. type: string name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret + or its key must be defined type: boolean required: - key @@ -1461,158 +4907,80 @@ spec: type: array envFrom: items: + description: EnvFromSource represents the source of + a set of ConfigMaps properties: configMapRef: + description: The ConfigMap to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the ConfigMap must + be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: + description: The Secret to select from properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string optional: + description: Specify whether the Secret must + be defined 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: - properties: - path: - type: string - pvc: - properties: - create: - properties: - accessModes: - items: - type: string - type: array - resources: - properties: - 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 - storageClassName: - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - type: string - ref: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - 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('^/[^:]*$') - type: object - x-kubernetes-validations: - - message: Ephemeral stores must have absolute paths. - rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') - : 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: Online store does not support S3 or GS - buckets. - rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - store: - properties: - secretKeyName: - 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)' + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string resources: + description: ResourceRequirements describes the compute + resource requirements. properties: claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - name @@ -1628,6 +4996,9 @@ spec: - 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object requests: additionalProperties: @@ -1636,23 +5007,40 @@ spec: - 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 + description: Requests describes the minimum amount + of compute resources required. type: object type: object tls: + description: TlsConfigs configures server TLS for a feast + service. properties: disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default type: boolean secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: tlsCrt: + description: defaults to "tls.crt" type: string tlsKey: + description: defaults to "tls.key" type: string type: object secretRef: + description: references the local k8s secret where + the TLS key and cert reside properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string type: object x-kubernetes-map-type: atomic @@ -1661,507 +5049,1529 @@ spec: - message: '`secretRef` required if `disable` is false.' rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) : true' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array type: object - registry: - properties: - local: - properties: - env: - items: + volumes: + description: Volumes specifies the volumes to mount in the + FeatureStore deployment. + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: |- + awsElasticBlockStore represents an AWS Disk resource that is attached to a + kubelet's host machine and then exposed to th + properties: + fsType: + description: fsType is the filesystem type of the + volume that you want to mount. + type: string + partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. + format: int32 + type: integer + readOnly: + description: |- + readOnly value true will force the readOnly setting in VolumeMounts. + More info: https://kubernetes. + type: boolean + volumeID: + description: |- + volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). + More info: https://kubernetes. + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk + in the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in + the blob storage + type: string + fsType: + description: |- + fsType is Filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage accoun' + type: string + readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime + properties: + monitors: + description: |- + monitors is Required: Monitors is a collection of Ceph monitors + More info: https://examples.k8s. + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' + type: string + readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty.' properties: name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. 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: + x-kubernetes-map-type: atomic + user: + description: |- + user is optional: User is the rados user name, default is admin + More info: https://examples.k8s. + type: string + required: + - monitors + type: object + cinder: + description: |- + cinder represents a cinder volume attached and mounted on kubelets host machine. + More info: https://examples.k8s. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + type: string + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef is optional: points to a secret object containing parameters used to connect + to OpenStack. properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. 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: - properties: - path: - type: string - pvc: - properties: - create: - properties: - accessModes: - items: - type: string - type: array - resources: - properties: - 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 - storageClassName: - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - type: string - ref: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - 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: - 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: + x-kubernetes-map-type: atomic + volumeID: + description: |- + volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default.' + format: int32 + type: integer + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum + items: + description: Maps a string key to a path within + a volume. properties: - secretKeyName: + key: + description: key is the key to project. type: string - secretRef: + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta fea + properties: + driver: + description: driver is the name of the CSI driver + that handles this volume. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". + type: string + nodePublishSecretRef: + description: |- + nodePublishSecretRef is a reference to the secret object containing + sensitive information to pass to the CSI driver to c + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: |- + readOnly specifies a read-only configuration for the volume. + Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: |- + volumeAttributes stores driver-specific properties that are passed to the CSI + driver. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name, + namespace and uid are supported.' properties: - name: - default: "" + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath type: object x-kubernetes-map-type: atomic - type: - enum: - - sql - - snowflake.registry + mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path.' type: string + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic required: - - secretRef - - type + - path 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: + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + description: |- + emptyDir represents a temporary directory that shares a pod's lifetime. + More info: https://kubernetes. + properties: + medium: + description: medium represents what type of storage + medium should back this directory. + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: sizeLimit is the total amount of local + storage required for this EmptyDir volume. + 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 + ephemeral: + description: ephemeral represents a volume that is handled + by a cluster storage driver. + properties: + volumeClaimTemplate: + description: Will be used to create a stand-alone + PVC to provision the volume. + properties: + metadata: + description: |- + May contain labels and annotations that will be copied into the PVC + when creating it. + type: object + spec: + description: The specification for the PersistentVolumeClaim. properties: - name: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s. + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking. + type: string + required: + - kind + - name + type: object + resources: + description: resources represents the minimum + resources the volume should have. + properties: + 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 + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + 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 + description: Requests describes the + minimum amount of compute resources + required. + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes. + type: string + volumeAttributesClassName: + description: volumeAttributesClassName may + be used to set the VolumeAttributesClass + used by this claim. + type: string + volumeMode: + description: volumeMode defines what type + of volume is required by the claim. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. 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 - remote: - properties: - feastRef: - properties: - name: + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' + items: type: string - namespace: + type: array + x-kubernetes-list-type: atomic + wwids: + description: "wwids Optional: FC volume world wide + identifiers (wwids)\nEither wwids or combination + of targetWWNs and lun must be set, " + items: type: string - required: - - name - type: object - hostname: - type: string - tls: - properties: - certName: + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + description: |- + flexVolume represents a generic volume resource that is + provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to + use for this volume. + type: string + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + options: + additionalProperties: type: string - configMapRef: - properties: - name: - default: "" - type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: |- + readOnly is Optional: defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef is Optional: secretRef is reference to the secret object containing + sensitive information to pass to the plugi + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. + properties: + datasetName: + description: |- + datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker + should be considered as depreca + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: |- + gcePersistentDisk represents a GCE Disk resource that is attached to a + kubelet's host machine and then exposed to the po + properties: + fsType: + description: fsType is filesystem type of the volume + that you want to mount. + type: string + partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. + format: int32 + type: integer + pdName: + description: |- + pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. + More info: https://kubernetes. + type: string + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://kubernetes. + type: boolean + required: + - pdName + type: object + gitRepo: + description: |- + gitRepo represents a git repository at a particular revision. + DEPRECATED: GitRepo is deprecated. + properties: + directory: + description: |- + directory is the target directory name. + Must not contain or start with '..'. If '. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the + specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: |- + glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. + properties: + endpoints: + description: |- + endpoints is the endpoint name that details Glusterfs topology. + More info: https://examples.k8s. + type: string + path: + description: |- + path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod + type: string + readOnly: + description: |- + readOnly here will force the Glusterfs volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: |- + hostPath represents a pre-existing file or directory on the host + machine that is directly exposed to the container. + properties: + path: + description: |- + path of the directory on the host. + If the path is a symlink, it will follow the link to the real path. + type: string + type: + description: |- + type for HostPath Volume + Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + type: string + required: + - path + type: object + iscsi: + description: |- + iscsi represents an ISCSI Disk resource that is attached to a + kubelet's host machine and then exposed to the pod. + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: fsType is the filesystem type of the + volume that you want to mount. + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: |- + iscsiInterface is the interface Name that uses an iSCSI transport. + Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal + List. + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: |- + name of the volume. + Must be a DNS_LABEL and unique within the pod. + More info: https://kubernetes. + type: string + nfs: + description: |- + nfs represents an NFS mount on the host that shares a pod's lifetime + More info: https://kubernetes. + properties: + path: + description: |- + path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs + type: string + readOnly: + description: |- + readOnly here will force the NFS export to be mounted with read-only permissions. + Defaults to false. + type: boolean + server: + description: |- + server is the hostname or IP address of the NFS server. + More info: https://kubernetes. + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: |- + persistentVolumeClaimVolumeSource represents a reference to a + PersistentVolumeClaim in the same namespace. + properties: + claimName: + description: claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + type: string + readOnly: + description: |- + readOnly Will force the ReadOnly setting in VolumeMounts. + Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: |- + fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating system. + Ex. + type: string + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources + secrets, configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + clusterTrustBundle: + description: ClusterTrustBundle allows a pod + to access the `.spec. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. + type: string + required: + - path + type: object + configMap: + description: configMap information about the + configMap data to project + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volum + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: optional specify whether + the ConfigMap or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about + the downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name, namespace and uid + are supported.' + properties: + apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field + to select in the specified + API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal valu + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path.' + type: string + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. + properties: + containerName: + description: 'Container name: + required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + description: secret information about the + secret data to project + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended + audience of the token. + type: string + expirationSeconds: + description: |- + expirationSeconds is the requested duration of validity of the service + account token. + format: int64 + type: integer + path: + description: |- + path is the path relative to the mount point of the file to project the + token into. + type: string + required: + - path + type: object type: object - x-kubernetes-map-type: atomic - required: - - certName - - configMapRef - type: object - type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, - c)' - type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.local), has(self.remote)].exists_one(c, - c)' - ui: - properties: - env: - items: + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime properties: - name: + group: + description: |- + group to map volume access to + Default is no group type: string - value: + readOnly: + description: |- + readOnly here will force the Quobyte volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: |- + registry represents a single or multiple Quobyte Registry services + specified as a string as host:port pair (multiple ent + type: string + tenant: + description: |- + tenant owning the given Quobyte volume in the Backend + Used with dynamically provisioned Quobyte volumes, value is set by + type: string + user: + description: |- + user to map volume access to + Defaults to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. 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 + - registry + - volume type: object - type: array - envFrom: - items: + rbd: + description: |- + rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. + More info: https://examples.k8s. properties: - configMapRef: + fsType: + description: fsType is the filesystem type of the + volume that you want to mount. + type: string + image: + description: |- + image is the rados image name. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + keyring: + description: |- + keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. + More info: https://examples.k8s. + type: string + monitors: + description: |- + monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + description: |- + pool is the rados pool name. + Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://examples.k8s. + type: boolean + secretRef: + description: |- + secretRef is name of the authentication secret for RBDUser. If provided + overrides keyring. + Default is nil. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - optional: - type: boolean type: object x-kubernetes-map-type: atomic - prefix: + user: + description: |- + user is the rados user name. + Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean secretRef: + description: |- + secretRef references to the secret for ScaleIO user and other + sensitive information. properties: name: default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - optional: - type: boolean type: object x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: |- + volumeName is the name of a volume already created in the ScaleIO system + that is associated with this volume source. + type: string + required: + - gateway + - secretRef + - system type: object - type: array - image: - type: string - imagePullPolicy: - type: string - logLevel: - enum: - - debug - - info - - warning - - error - - critical - type: string - resources: - properties: - claims: + secret: + description: |- + secret represents a secret that should populate this volume. + More info: https://kubernetes. + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default.' + format: int32 + type: integer items: + description: |- + items If unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume a + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: |- + secretName is the name of the secret in the pod's namespace to use. + More info: https://kubernetes. + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef specifies the secret to use for obtaining the StorageOS API + credentials. properties: name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. 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 + x-kubernetes-map-type: atomic + volumeName: + description: |- + volumeName is the human-readable name of the StorageOS volume. Volume + names are only unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine + properties: + fsType: + description: |- + fsType is filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array type: object required: - feastProject type: object clientConfigMap: + description: ConfigMap in this namespace containing a client `feature_store.yaml` + for this feast deployment type: string conditions: items: + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. format: date-time type: string message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. maxLength: 32768 type: string observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if . format: int64 minimum: 0 type: integer reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: + description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -2178,6 +6588,8 @@ spec: phase: type: string serviceHostnames: + description: ServiceHostnames defines the service hostnames in the + format of :, e.g. example.svc.cluster.local:80 properties: offlineStore: type: string diff --git a/infra/feast-operator/config/component_metadata.yaml b/infra/feast-operator/config/component_metadata.yaml index d4c7621f471..cbe44e473af 100644 --- a/infra/feast-operator/config/component_metadata.yaml +++ b/infra/feast-operator/config/component_metadata.yaml @@ -1,5 +1,5 @@ # This file is required to configure Feast release information for ODH/RHOAI Operator releases: - name: Feast - version: 0.45.0 + version: 0.46.0 repoUrl: https://github.com/feast-dev/feast diff --git a/infra/feast-operator/config/default/related_image_fs_patch.yaml b/infra/feast-operator/config/default/related_image_fs_patch.yaml index 621a1458a5b..890e4a8f45c 100644 --- a/infra/feast-operator/config/default/related_image_fs_patch.yaml +++ b/infra/feast-operator/config/default/related_image_fs_patch.yaml @@ -2,4 +2,4 @@ path: "/spec/template/spec/containers/0/env/0" value: name: RELATED_IMAGE_FEATURE_SERVER - value: docker.io/feastdev/feature-server:0.45.0 + value: docker.io/feastdev/feature-server:0.46.0 diff --git a/infra/feast-operator/config/manager/kustomization.yaml b/infra/feast-operator/config/manager/kustomization.yaml index 5bf6483d849..bdf2ea9398c 100644 --- a/infra/feast-operator/config/manager/kustomization.yaml +++ b/infra/feast-operator/config/manager/kustomization.yaml @@ -5,4 +5,4 @@ kind: Kustomization images: - name: controller newName: feastdev/feast-operator - newTag: 0.45.0 + newTag: 0.46.0 diff --git a/infra/feast-operator/config/overlays/odh/params.env b/infra/feast-operator/config/overlays/odh/params.env index 14398caccc8..3e846e9ccc6 100644 --- a/infra/feast-operator/config/overlays/odh/params.env +++ b/infra/feast-operator/config/overlays/odh/params.env @@ -1,2 +1,2 @@ -RELATED_IMAGE_FEAST_OPERATOR=docker.io/feastdev/feast-operator:0.45.0 -RELATED_IMAGE_FEATURE_SERVER=docker.io/feastdev/feature-server:0.45.0 \ No newline at end of file +RELATED_IMAGE_FEAST_OPERATOR=docker.io/feastdev/feast-operator:0.46.0 +RELATED_IMAGE_FEATURE_SERVER=docker.io/feastdev/feature-server:0.46.0 \ No newline at end of file diff --git a/infra/feast-operator/dist/install.yaml b/infra/feast-operator/dist/install.yaml index 2e2e3e279c2..7ab4fc3b72b 100644 --- a/infra/feast-operator/dist/install.yaml +++ b/infra/feast-operator/dist/install.yaml @@ -6933,8 +6933,8 @@ spec: - /manager env: - name: RELATED_IMAGE_FEATURE_SERVER - value: docker.io/feastdev/feature-server:0.45.0 - image: feastdev/feast-operator:0.45.0 + value: docker.io/feastdev/feature-server:0.46.0 + image: feastdev/feast-operator:0.46.0 livenessProbe: httpGet: path: /healthz diff --git a/java/pom.xml b/java/pom.xml index 059692b0c54..d7076ef501e 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -35,7 +35,7 @@ - 0.45.0 + 0.46.0 https://github.com/feast-dev/feast UTF-8 diff --git a/sdk/python/feast/ui/package.json b/sdk/python/feast/ui/package.json index b1c524233ba..de74a03f2af 100644 --- a/sdk/python/feast/ui/package.json +++ b/sdk/python/feast/ui/package.json @@ -6,7 +6,7 @@ "@elastic/datemath": "^5.0.3", "@elastic/eui": "^72.0.0", "@emotion/react": "^11.9.0", - "@feast-dev/feast-ui": "0.44.0", + "@feast-dev/feast-ui": "0.46.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.2.0", "@testing-library/user-event": "^13.5.0", diff --git a/sdk/python/feast/ui/yarn.lock b/sdk/python/feast/ui/yarn.lock index 47b067c806d..896c9877f14 100644 --- a/sdk/python/feast/ui/yarn.lock +++ b/sdk/python/feast/ui/yarn.lock @@ -1570,10 +1570,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@feast-dev/feast-ui@0.44.0": - version "0.44.0" - resolved "https://registry.yarnpkg.com/@feast-dev/feast-ui/-/feast-ui-0.44.0.tgz#71708bc66b0bef9b3961bdf236295e0669e63ba9" - integrity sha512-OZkcW0IhFd6dMoi8oKz5ssKO1iPz8SeEoeu0kA4qE6UNEE3K2MnsOsMhRSn8r6DKAl/wLV1LbjCHPNifk824jQ== +"@feast-dev/feast-ui@0.46.0": + version "0.46.0" + resolved "https://registry.yarnpkg.com/@feast-dev/feast-ui/-/feast-ui-0.46.0.tgz#2ab5fa42b43c20829a6cbb44e66df8f4ee2597ae" + integrity sha512-d4EgsfhXH1nlpMGuD8M/D/2Z7OryUQkg4cUWvGadj06bwoUM60+ku0gGUZb2PnbfgdUdMrB5p7VS9di0jFurNA== dependencies: "@elastic/datemath" "^5.0.3" "@elastic/eui" "^95.12.0" diff --git a/ui/package.json b/ui/package.json index 7913d63f281..f2ac73ef595 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "@feast-dev/feast-ui", - "version": "0.45.0", + "version": "0.46.0", "private": false, "files": [ "dist"