Skip to content

Commit

Permalink
feat: Add possibility to define feature_store.yaml path with env vari…
Browse files Browse the repository at this point in the history
…able (#3231)

* Add possibility to define feature_store.yaml path with environment variable

Signed-off-by: arcabucero <[email protected]>

* Add possibility to define feature_store.yaml path with environment variable for aws and lambda_engine

Signed-off-by: arcabucero <[email protected]>

* Add test for overriding feature_store.yaml path with environment variable

Signed-off-by: arcabucero <[email protected]>

Signed-off-by: arcabucero <[email protected]>
  • Loading branch information
arcabucero authored Sep 26, 2022
1 parent d7d33c9 commit 95fdb19
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 4 deletions.
2 changes: 1 addition & 1 deletion sdk/python/feast/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def cli(
ctx.obj["FS_YAML_FILE"] = (
Path(feature_store_yaml).absolute()
if feature_store_yaml
else ctx.obj["CHDIR"] / "feature_store.yaml"
else utils.get_default_yaml_file_path(ctx.obj["CHDIR"])
)
try:
level = getattr(logging, log_level.upper())
Expand Down
3 changes: 3 additions & 0 deletions sdk/python/feast/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
# feature_store.yaml environment variable name for remote feature server
FEATURE_STORE_YAML_ENV_NAME: str = "FEATURE_STORE_YAML_BASE64"

# feature_store.yaml path environment variable name
FEAST_FS_YAML_FILE_PATH_ENV_NAME: str = "FEAST_FS_YAML_FILE_PATH"

# Environment variable for registry
REGISTRY_ENV_NAME: str = "REGISTRY_BASE64"

Expand Down
2 changes: 1 addition & 1 deletion sdk/python/feast/feature_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def __init__(
self.config = load_repo_config(self.repo_path, fs_yaml_file)
else:
self.config = load_repo_config(
self.repo_path, Path(self.repo_path) / "feature_store.yaml"
self.repo_path, utils.get_default_yaml_file_path(self.repo_path)
)

registry_config = self.config.get_registry_config()
Expand Down
6 changes: 5 additions & 1 deletion sdk/python/feast/infra/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from colorama import Fore, Style

from feast import utils
from feast.constants import (
AWS_LAMBDA_FEATURE_SERVER_IMAGE,
AWS_LAMBDA_FEATURE_SERVER_REPOSITORY,
Expand Down Expand Up @@ -113,7 +114,10 @@ def _deploy_feature_server(self, project: str, image_uri: str):

if not self.repo_config.repo_path:
raise RepoConfigPathDoesNotExist()
with open(self.repo_config.repo_path / "feature_store.yaml", "rb") as f:

with open(
utils.get_default_yaml_file_path(self.repo_config.repo_path), "rb"
) as f:
config_bytes = f.read()
config_base64 = base64.b64encode(config_bytes).decode()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from pydantic import StrictStr
from tqdm import tqdm

from feast import utils
from feast.batch_feature_view import BatchFeatureView
from feast.constants import FEATURE_STORE_YAML_ENV_NAME
from feast.entity import Entity
Expand Down Expand Up @@ -137,7 +138,7 @@ def __init__(
)
repo_path = self.repo_config.repo_path
assert repo_path
feature_store_path = repo_path / "feature_store.yaml"
feature_store_path = utils.get_default_yaml_file_path(repo_path)
self.feature_store_base64 = str(
base64.b64encode(bytes(feature_store_path.read_text(), "UTF-8")), "UTF-8"
)
Expand Down
11 changes: 11 additions & 0 deletions sdk/python/feast/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import os
import typing
from collections import defaultdict
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional, Tuple, Union

import pandas as pd
Expand All @@ -9,6 +11,7 @@
from dateutil.tz import tzlocal
from pytz import utc

from feast.constants import FEAST_FS_YAML_FILE_PATH_ENV_NAME
from feast.entity import Entity
from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto
from feast.protos.feast.types.Value_pb2 import Value as ValueProto
Expand Down Expand Up @@ -51,6 +54,14 @@ def maybe_local_tz(t: datetime) -> datetime:
return t


def get_default_yaml_file_path(repo_path: Path) -> Path:
if FEAST_FS_YAML_FILE_PATH_ENV_NAME in os.environ:
yaml_path = os.environ[FEAST_FS_YAML_FILE_PATH_ENV_NAME]
return Path(yaml_path)
else:
return repo_path / "feature_store.yaml"


def _get_requested_feature_views_to_features_dict(
feature_refs: List[str],
feature_views: List["FeatureView"],
Expand Down
17 changes: 17 additions & 0 deletions sdk/python/tests/unit/cli/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import os
import tempfile
from contextlib import contextmanager
from pathlib import Path
from textwrap import dedent
from unittest import mock

from assertpy import assertpy

Expand Down Expand Up @@ -85,6 +87,21 @@ def test_3rd_party_registry_store_with_fs_yaml_override() -> None:
assertpy.assert_that(return_code).is_equal_to(0)


def test_3rd_party_registry_store_with_fs_yaml_override_by_env_var() -> None:
runner = CliRunner()

fs_yaml_file = "test_fs.yaml"
with setup_third_party_registry_store_repo(
"foo.registry_store.FooRegistryStore", fs_yaml_file_name=fs_yaml_file
) as repo_path:
custom_yaml_path = os.path.join(repo_path, fs_yaml_file)
with mock.patch.dict(
"os.environ", {"FEAST_FS_YAML_FILE_PATH": custom_yaml_path}, clear=True
):
return_code, output = runner.run_with_output(["apply"], cwd=repo_path)
assertpy.assert_that(return_code).is_equal_to(0)


@contextmanager
def setup_third_party_provider_repo(provider_name: str):
with tempfile.TemporaryDirectory() as repo_dir_name:
Expand Down

0 comments on commit 95fdb19

Please sign in to comment.