diff --git a/docs/reference/alpha-on-demand-feature-view.md b/docs/reference/alpha-on-demand-feature-view.md index 17a747d526..01b47d13dc 100644 --- a/docs/reference/alpha-on-demand-feature-view.md +++ b/docs/reference/alpha-on-demand-feature-view.md @@ -2,10 +2,6 @@ **Warning**: This is an _experimental_ feature. It's intended for early testing and feedback, and could change without warnings in future releases. -{% hint style="info" %} -To enable this feature, run **`feast alpha enable on_demand_transforms`** -{% endhint %} - ## Overview On demand feature views allows data scientists to use existing features and request time data (features only available at request time) to transform and create new features. Users define python transformation logic which is executed in both historical retrieval and online retrieval paths. diff --git a/docs/reference/feature-servers/README.md b/docs/reference/feature-servers/README.md index ec13973500..f9a40104c3 100644 --- a/docs/reference/feature-servers/README.md +++ b/docs/reference/feature-servers/README.md @@ -9,3 +9,7 @@ Feast users can choose to retrieve features from a feature server, as opposed to {% content-ref url="go-feature-server.md" %} [go-feature-server.md](go-feature-server.md) {% endcontent-ref %} + +{% content-ref url="alpha-aws-lambda-feature-server.md" %} +[alpha-aws-lambda-feature-server.md](alpha-aws-lambda-feature-server.md) +{% endcontent-ref %} \ No newline at end of file diff --git a/docs/reference/feature-servers/alpha-aws-lambda-feature-server.md b/docs/reference/feature-servers/alpha-aws-lambda-feature-server.md index c11d476405..caf5542bdc 100644 --- a/docs/reference/feature-servers/alpha-aws-lambda-feature-server.md +++ b/docs/reference/feature-servers/alpha-aws-lambda-feature-server.md @@ -2,10 +2,6 @@ **Warning**: This is an _experimental_ feature. It's intended for early testing and feedback, and could change without warnings in future releases. -{% hint style="info" %} -To enable this feature, run **`feast alpha enable aws_lambda_feature_server`** -{% endhint %} - ## Overview The AWS Lambda feature server is an HTTP endpoint that serves features with JSON I/O, deployed as a Docker image through AWS Lambda and AWS API Gateway. This enables users to get features from Feast using any programming language that can make HTTP requests. A [local feature server](python-feature-server.md) is also available. A remote feature server on GCP Cloud Run is currently being developed. @@ -27,9 +23,6 @@ offline_store: database: feast s3_staging_location: s3://feast/redshift/tests/staging_location iam_role: arn:aws:iam::{aws_account}:role/redshift_s3_access_role -flags: - alpha_features: true - aws_lambda_feature_server: true feature_server: enabled: True execution_role_name: arn:aws:iam::{aws_account}:role/lambda_execution_role @@ -41,12 +34,12 @@ If enabled, the feature server will be deployed during `feast apply`. After it i Feast requires the following permissions in order to deploy and teardown AWS Lambda feature server: -| Permissions | Resources | -| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -|

lambda:CreateFunction

lambda:GetFunction

lambda:DeleteFunction

lambda:AddPermission

lambda:UpdateFunctionConfiguration

| arn:aws:lambda:\:\:function:feast-\* | -|

ecr:CreateRepository

ecr:DescribeRepositories

ecr:DeleteRepository

ecr:PutImage

ecr:DescribeImages

ecr:BatchDeleteImage

ecr:CompleteLayerUpload

ecr:UploadLayerPart

ecr:InitiateLayerUpload

ecr:BatchCheckLayerAvailability

ecr:GetDownloadUrlForLayer

ecr:GetRepositoryPolicy

ecr:SetRepositoryPolicy

ecr:GetAuthorizationToken

| \* | -| iam:PassRole | arn:aws:iam::\:role/ | -| apigateway:\* |

arn:aws:apigateway:::/apis//routes//routeresponses

arn:aws:apigateway:::/apis//routes//routeresponses/

arn:aws:apigateway:::/apis//routes/

arn:aws:apigateway:::/apis//routes

arn:aws:apigateway:::/apis//integrations

arn:aws:apigateway:::/apis//stages//routesettings/

arn:aws:apigateway:::/apis/

arn:aws:apigateway:*::/apis

| +| Permissions | Resources | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +|

lambda:CreateFunction

lambda:GetFunction

lambda:DeleteFunction

lambda:AddPermission

lambda:UpdateFunctionConfiguration

| arn:aws:lambda:\:\:function:feast-\* | +|

ecr:CreateRepository

ecr:DescribeRepositories

ecr:DeleteRepository

ecr:PutImage

ecr:DescribeImages

ecr:BatchDeleteImage

ecr:CompleteLayerUpload

ecr:UploadLayerPart

ecr:InitiateLayerUpload

ecr:BatchCheckLayerAvailability

ecr:GetDownloadUrlForLayer

ecr:GetRepositoryPolicy

ecr:SetRepositoryPolicy

ecr:GetAuthorizationToken

| \* | +|

iam:PassRole

| arn:aws:iam::\:role/ | +|

apigateway:*

|

arn:aws:apigateway:*::/apis/*/routes/*/routeresponses

arn:aws:apigateway:*::/apis/*/routes/*/routeresponses/*

arn:aws:apigateway:*::/apis/*/routes/*

arn:aws:apigateway:*::/apis/*/routes

arn:aws:apigateway:*::/apis/*/integrations

arn:aws:apigateway:*::/apis/*/stages/*/routesettings/*

arn:aws:apigateway:*::/apis/*

arn:aws:apigateway:*::/apis

| The following inline policy can be used to grant Feast the necessary permissions: diff --git a/examples/java-demo/README.md b/examples/java-demo/README.md index b908bb7625..2b1d7f75a5 100644 --- a/examples/java-demo/README.md +++ b/examples/java-demo/README.md @@ -39,9 +39,6 @@ For this tutorial, we setup Feast with Redis, using the Feast CLI to register an connection_string: localhost:6379,password=[YOUR PASSWORD] offline_store: type: file - flags: - alpha_features: true - on_demand_transforms: true ``` 4. Run `feast apply` to apply your local features to the remote registry 5. Materialize features to the online store: diff --git a/examples/java-demo/feature_repo/feature_store.yaml b/examples/java-demo/feature_repo/feature_store.yaml index 91c65b512a..03e7c5cc9c 100644 --- a/examples/java-demo/feature_repo/feature_store.yaml +++ b/examples/java-demo/feature_repo/feature_store.yaml @@ -6,6 +6,3 @@ online_store: connection_string: localhost:6379,password=[YOUR PASSWORD] offline_store: type: file -flags: - alpha_features: true - on_demand_transforms: true diff --git a/infra/charts/feast/charts/transformation-service/config/feature_store.yaml b/infra/charts/feast/charts/transformation-service/config/feature_store.yaml index 555e93a306..c003b87cc2 100644 --- a/infra/charts/feast/charts/transformation-service/config/feature_store.yaml +++ b/infra/charts/feast/charts/transformation-service/config/feature_store.yaml @@ -2,7 +2,4 @@ registry: path: {{ .Values.global.registry.path }} cache_ttl_seconds: {{ .Values.global.registry.cache_ttl_seconds }} provider: local -project: {{ .Values.global.project }} -flags: - on_demand_transforms: true - alpha_features: true \ No newline at end of file +project: {{ .Values.global.project }} \ No newline at end of file diff --git a/java/serving/src/test/resources/docker-compose/feast10/feature_store.yaml b/java/serving/src/test/resources/docker-compose/feast10/feature_store.yaml index 2e6625c025..8e863caa69 100644 --- a/java/serving/src/test/resources/docker-compose/feast10/feature_store.yaml +++ b/java/serving/src/test/resources/docker-compose/feast10/feature_store.yaml @@ -5,6 +5,3 @@ online_store: type: redis connection_string: "redis:6379,password=testpw" offline_store: {} -flags: - alpha_features: true - on_demand_transforms: true diff --git a/sdk/python/docs/source/feast.rst b/sdk/python/docs/source/feast.rst index c000ac2e2b..b1fb70a362 100644 --- a/sdk/python/docs/source/feast.rst +++ b/sdk/python/docs/source/feast.rst @@ -169,14 +169,6 @@ feast.field module :undoc-members: :show-inheritance: -feast.flags module ------------------- - -.. automodule:: feast.flags - :members: - :undoc-members: - :show-inheritance: - feast.flags\_helper module -------------------------- diff --git a/sdk/python/feast/cli.py b/sdk/python/feast/cli.py index 153c1a5ddd..8c1f988e36 100644 --- a/sdk/python/feast/cli.py +++ b/sdk/python/feast/cli.py @@ -25,7 +25,7 @@ from dateutil import parser from pygments import formatters, highlight, lexers -from feast import flags, flags_helper, utils +from feast import utils from feast.constants import DEFAULT_FEATURE_TRANSFORMATION_SERVER_PORT from feast.errors import FeastObjectNotFoundException, FeastProviderLoginError from feast.feature_store import FeatureStore @@ -691,113 +691,6 @@ def serve_transformations_command(ctx: click.Context, port: int): store.serve_transformations(port) -@cli.group(name="alpha") -def alpha_cmd(): - """ - Access alpha features - """ - pass - - -@alpha_cmd.command("list") -@click.pass_context -def list_alpha_features(ctx: click.Context): - """ - Lists all alpha features - """ - repo = ctx.obj["CHDIR"] - cli_check_repo(repo) - repo_path = str(repo) - store = FeatureStore(repo_path=repo_path) - - flags_to_show = flags.FLAG_NAMES.copy() - flags_to_show.remove(flags.FLAG_ALPHA_FEATURES_NAME) - print("Alpha features:") - for flag in flags_to_show: - enabled_string = ( - "enabled" - if flags_helper.feature_flag_enabled(store.config, flag) - else "disabled" - ) - print(f"{flag}: {enabled_string}") - - -@alpha_cmd.command("enable-all") -@click.pass_context -def enable_alpha_features(ctx: click.Context): - """ - Enables all alpha features - """ - repo = ctx.obj["CHDIR"] - cli_check_repo(repo) - repo_path = str(repo) - store = FeatureStore(repo_path=repo_path) - - if store.config.flags is None: - store.config.flags = {} - for flag_name in flags.FLAG_NAMES: - store.config.flags[flag_name] = True - store.config.write_to_path(Path(repo_path)) - - -@alpha_cmd.command("enable") -@click.argument("name", type=click.STRING) -@click.pass_context -def enable_alpha_feature(ctx: click.Context, name: str): - """ - Enables an alpha feature - """ - if name not in flags.FLAG_NAMES: - raise ValueError(f"Flag name, {name}, not valid.") - - repo = ctx.obj["CHDIR"] - cli_check_repo(repo) - repo_path = str(repo) - store = FeatureStore(repo_path=repo_path) - - if store.config.flags is None: - store.config.flags = {} - store.config.flags[flags.FLAG_ALPHA_FEATURES_NAME] = True - store.config.flags[name] = True - store.config.write_to_path(Path(repo_path)) - - -@alpha_cmd.command("disable") -@click.argument("name", type=click.STRING) -@click.pass_context -def disable_alpha_feature(ctx: click.Context, name: str): - """ - Disables an alpha feature - """ - if name not in flags.FLAG_NAMES: - raise ValueError(f"Flag name, {name}, not valid.") - - repo = ctx.obj["CHDIR"] - cli_check_repo(repo) - repo_path = str(repo) - store = FeatureStore(repo_path=repo_path) - - if store.config.flags is None or name not in store.config.flags: - return - store.config.flags[name] = False - store.config.write_to_path(Path(repo_path)) - - -@alpha_cmd.command("disable-all") -@click.pass_context -def disable_alpha_features(ctx: click.Context): - """ - Disables all alpha features - """ - repo = ctx.obj["CHDIR"] - cli_check_repo(repo) - repo_path = str(repo) - store = FeatureStore(repo_path=repo_path) - - store.config.flags = None - store.config.write_to_path(Path(repo_path)) - - @cli.command("validate") @click.option( "--feature-service", diff --git a/sdk/python/feast/errors.py b/sdk/python/feast/errors.py index 0279d125da..518d648533 100644 --- a/sdk/python/feast/errors.py +++ b/sdk/python/feast/errors.py @@ -319,14 +319,6 @@ def __init__(self, feature_view_name: str): ) -class ExperimentalFeatureNotEnabled(Exception): - def __init__(self, feature_flag_name: str): - super().__init__( - f"You are attempting to use an experimental feature that is not enabled. Please run " - f"`feast alpha enable {feature_flag_name}` " - ) - - class RepoConfigPathDoesNotExist(Exception): def __init__(self): super().__init__("The repo_path attribute does not exist for the repo_config.") diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index c4ccc9a648..a1b370a4cc 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -40,7 +40,7 @@ from google.protobuf.timestamp_pb2 import Timestamp from tqdm import tqdm -from feast import feature_server, flags, flags_helper, ui_server, utils +from feast import feature_server, ui_server, utils from feast.base_feature_view import BaseFeatureView from feast.batch_feature_view import BatchFeatureView from feast.data_source import DataSource, PushMode @@ -50,7 +50,6 @@ from feast.entity import Entity from feast.errors import ( EntityNotFoundException, - ExperimentalFeatureNotEnabled, FeatureNameCollisionError, FeatureViewNotFoundException, RequestDataNotFoundInEntityDfException, @@ -502,8 +501,8 @@ def _get_features( ) if feature_service_from_registry != _features: warnings.warn( - "The FeatureService object that has been passed in as an argument is" - "inconsistent with the version from Registry. Potentially a newer version" + "The FeatureService object that has been passed in as an argument is " + "inconsistent with the version from the registry. Potentially a newer version " "of the FeatureService has been applied to the registry." ) for projection in feature_service_from_registry.feature_view_projections: @@ -533,11 +532,12 @@ def _validate_all_feature_views( sfvs_to_update: List[StreamFeatureView], ): """Validates all feature views.""" - if ( - not flags_helper.enable_on_demand_feature_views(self.config) - and len(odfvs_to_update) > 0 - ): - raise ExperimentalFeatureNotEnabled(flags.FLAG_ON_DEMAND_TRANSFORM_NAME) + if len(odfvs_to_update) > 0: + warnings.warn( + "On demand feature view is an experimental feature. " + "This API is stable, but the functionality does not scale well for offline retrieval", + RuntimeWarning, + ) set_usage_attribute("odfv", bool(odfvs_to_update)) @@ -2284,8 +2284,11 @@ def serve_ui( @log_exceptions_and_usage def serve_transformations(self, port: int) -> None: """Start the feature transformation server locally on a given port.""" - if not flags_helper.enable_on_demand_feature_views(self.config): - raise ExperimentalFeatureNotEnabled(flags.FLAG_ON_DEMAND_TRANSFORM_NAME) + warnings.warn( + "On demand feature view is an experimental feature. " + "This API is stable, but the functionality does not scale well for offline retrieval", + RuntimeWarning, + ) from feast import transformation_server diff --git a/sdk/python/feast/flags.py b/sdk/python/feast/flags.py deleted file mode 100644 index 26e20d81f6..0000000000 --- a/sdk/python/feast/flags.py +++ /dev/null @@ -1,10 +0,0 @@ -FLAG_ALPHA_FEATURES_NAME = "alpha_features" -FLAG_ON_DEMAND_TRANSFORM_NAME = "on_demand_transforms" -FLAG_AWS_LAMBDA_FEATURE_SERVER_NAME = "aws_lambda_feature_server" -ENV_FLAG_IS_TEST = "IS_TEST" - -FLAG_NAMES = { - FLAG_ALPHA_FEATURES_NAME, - FLAG_ON_DEMAND_TRANSFORM_NAME, - FLAG_AWS_LAMBDA_FEATURE_SERVER_NAME, -} diff --git a/sdk/python/feast/flags_helper.py b/sdk/python/feast/flags_helper.py index 7cf16dbf0b..4763f4a283 100644 --- a/sdk/python/feast/flags_helper.py +++ b/sdk/python/feast/flags_helper.py @@ -1,39 +1,11 @@ import os -from feast import flags -from feast.repo_config import RepoConfig +ENV_FLAG_IS_TEST = "IS_TEST" def _env_flag_enabled(name: str) -> bool: return os.getenv(name, default="False") == "True" -def feature_flag_enabled(repo_config: RepoConfig, flag_name: str) -> bool: - if is_test(): - return True - return ( - _alpha_feature_flag_enabled(repo_config) - and repo_config.flags is not None - and flag_name in repo_config.flags - and repo_config.flags[flag_name] - ) - - -def _alpha_feature_flag_enabled(repo_config: RepoConfig) -> bool: - return ( - repo_config.flags is not None - and flags.FLAG_ALPHA_FEATURES_NAME in repo_config.flags - and repo_config.flags[flags.FLAG_ALPHA_FEATURES_NAME] - ) - - def is_test() -> bool: - return _env_flag_enabled(flags.ENV_FLAG_IS_TEST) - - -def enable_on_demand_feature_views(repo_config: RepoConfig) -> bool: - return feature_flag_enabled(repo_config, flags.FLAG_ON_DEMAND_TRANSFORM_NAME) - - -def enable_aws_lambda_feature_server(repo_config: RepoConfig) -> bool: - return feature_flag_enabled(repo_config, flags.FLAG_AWS_LAMBDA_FEATURE_SERVER_NAME) + return _env_flag_enabled(ENV_FLAG_IS_TEST) diff --git a/sdk/python/feast/infra/aws.py b/sdk/python/feast/infra/aws.py index 145c55952e..523848f2f2 100644 --- a/sdk/python/feast/infra/aws.py +++ b/sdk/python/feast/infra/aws.py @@ -3,6 +3,7 @@ import logging import os import uuid +import warnings from datetime import datetime from pathlib import Path from tempfile import TemporaryFile @@ -22,15 +23,12 @@ from feast.errors import ( AwsAPIGatewayDoesNotExist, AwsLambdaDoesNotExist, - ExperimentalFeatureNotEnabled, IncompatibleRegistryStoreClass, RepoConfigPathDoesNotExist, S3RegistryBucketForbiddenAccess, S3RegistryBucketNotExist, ) from feast.feature_view import FeatureView -from feast.flags import FLAG_AWS_LAMBDA_FEATURE_SERVER_NAME -from feast.flags_helper import enable_aws_lambda_feature_server from feast.infra.feature_servers.aws_lambda.config import AwsLambdaFeatureServerConfig from feast.infra.passthrough_provider import PassthroughProvider from feast.infra.utils import aws_utils @@ -74,8 +72,11 @@ def update_infra( ) if self.repo_config.feature_server and self.repo_config.feature_server.enabled: - if not enable_aws_lambda_feature_server(self.repo_config): - raise ExperimentalFeatureNotEnabled(FLAG_AWS_LAMBDA_FEATURE_SERVER_NAME) + warnings.warn( + "AWS Lambda based feature serving is an experimental feature. " + "We do not guarantee that future changes will maintain backward compatibility.", + RuntimeWarning, + ) # Since the AWS Lambda feature server will attempt to load the registry, we # only allow the registry to be in S3. diff --git a/sdk/python/feast/repo_config.py b/sdk/python/feast/repo_config.py index 86cff7c8b0..278bc7da69 100644 --- a/sdk/python/feast/repo_config.py +++ b/sdk/python/feast/repo_config.py @@ -17,7 +17,6 @@ from pydantic.error_wrappers import ErrorWrapper from pydantic.typing import Dict, Optional, Union -from feast import flags from feast.errors import ( FeastFeatureServerTypeInvalidError, FeastFeatureServerTypeSetError, @@ -137,7 +136,7 @@ class RepoConfig(FeastBaseModel): """ FeatureServerConfig: Feature server configuration (optional depending on provider) """ flags: Any - """ Flags: Feature flags for experimental features (optional) """ + """ Flags (deprecated field): Feature flags for experimental features """ repo_path: Optional[Path] = None @@ -395,15 +394,9 @@ def _validate_flags(cls, v): if not isinstance(v, Dict): return - for flag_name, val in v.items(): - if flag_name not in flags.FLAG_NAMES: - _logger.warn( - "Unrecognized flag: %s. This feature may be invalid, or may refer " - "to a previously experimental feature which has graduated to production.", - flag_name, - ) - if type(val) is not bool: - raise ValueError(f"Flag value, {val}, not valid.") + _logger.warning( + "Flags are no longer necessary in Feast. Experimental features will log warnings instead." + ) return v diff --git a/ui/feature_repo/feature_store.yaml b/ui/feature_repo/feature_store.yaml index 31b27e2385..6ecad3eb51 100644 --- a/ui/feature_repo/feature_store.yaml +++ b/ui/feature_repo/feature_store.yaml @@ -5,6 +5,3 @@ online_store: type: sqlite offline_store: type: file -flags: - alpha_features: true - on_demand_transforms: true