From f8f442a46c27df9a1c8bf48819e5c96b6807161a Mon Sep 17 00:00:00 2001 From: Tommy Hughes Date: Tue, 11 Feb 2025 09:07:39 -0600 Subject: [PATCH] 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: {}